Linux - Socket网络套接字

OSI七层协议功能

物理层
面向物理传输媒体,屏蔽媒体的不同
主要定义物理设备标准,如网线的接口类型、光纤的接口类型、各种传输介质的传输速率等。它的主要作用是传输比特流(就是由1、0转化为电流强弱来进行传输,到达目的地后在转化为1、0,也就是我们常说的模数转换与数模转换)。这一层的数据叫做比特。
链路层
面向一条链路,成帧和无差错传输
主要将从物理层接收的数据进行MAC地址(网卡的地址)的封装与解封装。常把这一层的数据叫做帧。在这一层工作的设备是交换机,数据通过交换机来传输。
网络层
分配地址、面向多条链路、路由和流量控制
要将从下层接收到的数据进行IP地址(例192.168.0.1)的封装与解封装。在这一层工作的设备是路由器,常把这一层的数据叫做数据包。
传输层
面向两台主机通信,处理可靠传输细节,无差错、无失序传输
定义了一些传输数据的协议和端口号(WWW端口80等),如:TCP(传输控制协议),UDP(用户数据报协议)。 主要是将从下层接收的数据进行分段进行传输,到达目的地址后在进行重组。
会话层
面向一次会话,协调双方的交互、同步
主要在你的系统之间发起会话或或者接受会话请求(设备之间需要互相认识可以是IP也可以是MAC或者是主机名)
表示层
面向通信内容的表示,大家认同的描述方式
主要是进行对接收的数据进行解释、加密与解密、压缩与解压缩等(也就是把计算机能够识别的东西转换成人能够能识别的东西(如图片、声音等))
应用层
面向建立在通信基础上的应用,为应用提供通信服务,
主要是一些终端的应用,比如说FTP(各种文件下载),WEB(IE浏览),QQ之类的(你就把它理解成我们在电脑屏幕上可以看到的东西.就 是终端应用)

TCP协议特点

面向连接的可靠传输

端到端、建立/断开连接

正确、顺序传送数据

协议关注问题

IP数据报的丢失、重复、失序、延迟

发送和接收速度的匹配

系统重启动,一方连接信息丢失

网络拥塞

UDP协议特点

无连接

不需要在通信前建立连接

不使用控制报文

传输开销低

面向报文

不将报文分割,也不合并

UDP报文大小直接影响网络利用率

过小造成报头比率过大

过大造成MTU分片

尽力而为、任意交互

一对一、一对多、多对一和多对多

TCP/UDP端口号作为服务器程序标识

服务器启动时,首先在本地主机注册所使用的TCP/UDP端口号

客户通过与服务器指定的TCP端口建立连接(或直接向服务器指定的UDP端口发送信息)来访问特定服务

运行服务器程序的主机收到信息后,将其转交给注册该端口的服务器程序处理

Linux的网络分层结构

BSD Socket是通用接口,支持各种网络工作形式

INET Socket支持包括TCP/IP协议在内的Internet地址族

socket基本概念

Socket接口是应用程序与TCP/IP协议栈的接口

定义一组函数/例程,支持TCP/IP网络应用程序开发

与数据通信相关的系统调用是read()/write()

是一种文件描述符

一个套接字描述一个通信连接的一端

两个通信程序中各自有一个套接字来描述自己的

Socket不是TCP/IP标准的组成部分,但已成为事实上的工业标准

UNIX系列系统提供Socket

Windows系列、Macintosh系列、Solaris等亦提供

形式
(IP, PORT)
网络进程标识
<协议, 本地地址, 本地端口>
网间通信标识
<协议, 本地地址, 本地端口, 远程地址, 远程端口>
端口分类
公认端口:从0到1023
小于256的端口作为保留端口
注册端口:端口号从1024到49151 .
动态和/或私有端口:从49152到65535。理论上,不应为服务分配这些端口。实际上,机器通常从1024起分配动态端口。

基本socket API

socket()
创建一个新的Socket
close()
关闭一个Socket
bind()
将服务器(IP, Port)赋予Socket
listen()
等待到来的客户连接请求(TCP)
accept()
接受客户连接请求并建立连接(TCP)
connect()
向服务器发出连接请求
send()/recv()
发送/接收数据
字节顺序
大端模式(big   endian):高字节放到高地址上
小端模式(little   endian):高字节放到低地址上
主机字节顺序(HBO,Host Byte Order)
不同的机器HBO不相同,与CPU设计有关
Motorola 68k系列,HBO与NBO相同
Intel x86系列,HBO与NBO相反
网络字节顺序(NBO,Network Byte Order)
使用统一的字节顺序,避免兼容性问题
解决兼容性问题途径
往网络上发送前:转换成网络字节序
从网络接收数据:转换成主机字节序

头文件
#include <netinet/in.h>
函数原型
uint32_t htonl(uint32_t hostlong);
把32位值从主机字节序转换成网络字节序
uint16_t htons(uint16_t hostshort);
把16位值从主机字节序转换成网络字节序
uint32_t ntohl(uint32_t hostlong);
把32位值从网络字节序转换成主机字节序
uint16_t ntohs(uint16_t hostshort);
把16位值从网络字节序转换成主机字节序
说明
h代表host,n代表 network
s代表short,l代表long

socket()函数

功能
创建一个套接字
#include <sys/socket.h>
函数原型
int socket(int domain, int type, int protocol);
参数说明
domain:通信协议族,即地址族
type:套接字类型
protocol:通信协议
常设置为0 ,由内核根据指定的类型和协议族使用默认的协议
返回值
成功时,返回一个大于等于0的文件描述符
失败时,返回一个小于0的值

Linux支持的协议和地址族

地址 协议 协议描述
AF_UNIX PF_UNIX Unix域
AF_INET PF_INET TCP/IP(V4)
AF_INET6 PF_INET6 TCP/IP(V6)
AF_AX25 PF_AX25 业余无线电使用的AX.25
AF_IPX PF_IPX Novell的IPX
AF_APPLETALK PF_APPLETALK AppleTalk DDS
AF_NETROM PF_NETROM 业余无线电使用的 NetRom

套接字类型

流套接字(SOCK_STREAM)
可靠的、面向连接的通信
使用TCP协议
数据报套接字(SOCK_DGRAM)
无连接服务
使用UDP协议
原始套接字(SOCK_RAW)
允许对底层协议(如IP、ICMP)直接访问
int main(){
    ……
    int sockfd;
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
         perror(“socket”); 
   exit(1);
    }
    ……
}
函数原型
int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen)
int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t *optlen)
功能
控制套接字行为,如修改缓冲区大小、传输方式等
参数说明
level:指定控制套接字的层次
SOL_SOCKET:通用套接字选项
IPPROTO_IP:IP选项
IPPROTO_TCP:TCP选项
optname:指定控制方式(选项名称)
optval:获得/设置套接字选项值

SOL_SOCKET参数选项

SO_BROADCAST  允许发送广播数据                int
SO_DEBUG                  允许调试                                 int
SO_DONTROUTE           不查找路由                              int
SO_ERROR                 获得套接字错误                     int
SO_KEEPALIVE             保持连接                                 int
SO_LINGER                 延迟关闭连接                        struct linger
SO_OOBINLINE             带外数据放入正常数据流       int
SO_RCVBUF                 接收缓冲区大小                       int
SO_SNDBUF                 发送缓冲区大小                       int
SO_RCVLOWAT            接收缓冲区下限                        int
SO_SNDLOWAT             发送缓冲区下限                        int
SO_RCVTIMEO              接收超时                              struct timeval
SO_SNDTIMEO               发送超时                         struct timeval
SO_REUSERADDR         允许重用本地地址和端口        int
SO_TYPE                   获得套接字类型                        int
SO_BSDCOMPAT           与BSD系统兼容                        int 
IPPROTO_IP
IP_HDRINCL
在数据包中包含IP首部
IP_OPTINOS
IP首部选项
IP_TOS
服务类型
IP_TTL
生存时间
IPPRO_TCP
TCP_MAXSEG
TCP最大数据段的大小
TCP_NODELAY
不使用Nagle算法

套接字选项示例

更改发送/接收缓冲区大小
接收缓冲区
    int nRecvBuf=32*1024;         //设置为32Ksetsockopt(s, SOL_SOCKET, SO_RCVBUF, (const void*)&nRecvBuf, sizeof(int));
发送缓冲区
    int nSendBuf=32*1024;//设置为32Ksetsockopt(s, SOL_SOCKET, SO_SNDBUF, (const void*)&nSendBuf,sizeof(int));
说明
对于客户,SO_RCVBUF选项必须在connect之前设置
对于服务器,SO_RCVBUF选项必须在listen前设置

bind()函数

功能
将套接字地址与所创建的套接字号联系起来
客户端如果只想使用connect(),则无须使用该函数
#include <sys/socket.h>
函数原型
int bind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen);
参数说明
sockfd:调用socket返回的文件描述符
my_addr:保存地址信息(IP地址和端口)
addrlen:设置为 sizeof(struct sockaddr)
返回值
成功时,返回0
失败时,返回-1
    #include <string.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #define MYPORT 3490
    int main(){
        int sockfd;
        struct sockaddr_in my_addr;
        sockfd = socket(AF_INET, SOCK_STREAM, 0);
        my_addr.sin_family = AF_INET;
        my_addr.sin_port = htons(MYPORT);
        my_addr.sin_addr.s_addr = inet_addr("132.241.5.10");
        bind(sockfd, (struct sockaddr*)&my_addr, sizeof(struct
            sockaddr));
             …….
          }

sockaddr结构定义

功能
保存socket信息
结构
struct sockaddr {
   unsigned short  sa_family; /* 地址族,AF_xxx */ char sa_data[14];  /* 协议地址 */
 };
说明
sa_family一般为AF_INET(表示TCP/IP)
sa_data包含socket的IP地址和端口号
/include/linux/socket.h
功能
sockaddr的另一种表示形式
结构
struct sockaddr_in {  short int sin_family;      /* 地址族 */  unsigned short int sin_port; /* 端口号 */  struct in_addr sin_addr;    /* IP地址 */  unsigned char sin_zero[8]; /* 填充0,保持与struct sockaddr等长*/
};
说明
sin_zero用于将sockaddr_in结构填充到与struct sockaddr等长,可用bzero( )或memset( )函数将其置为0
当sin_port = 0时,系统随机选择一个未被使用的端口号
当sin_addr = INADDR_ANY时,表示填入本机IP地址
指向sockaddr_in的指针和指向sockaddr的指针可相互转换

connect()函数

功能
建立套接字连接
#include <sys/socket.h>
函数原型
int  connect(int  sockfd,  const struct sockaddr *serv_addr, socklen_t addrlen);
参数说明
sockfd:调用socket返回的文件描述符
serv_addr:远程主机IP 地址和端口
addrlen:设置为 sizeof(struct sockaddr)
返回值
成功时,返回0
失败时,返回-1
   #include <string.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #define DEST_IP "132.241.5.10"
    #define DEST_PORT 23
    int main() {
        int sockfd;
        struct sockaddr_in dest_addr;
        sockfd = socket(AF_INET, SOCK_STREAM, 0);
        dest_addr.sin_family = AF_INET;
        dest_addr.sin_port = htons(DEST_PORT);
        dest_addr.sin_addr.s_addr = inet_addr(DEST_IP);
        connect(sockfd, (struct sockaddr*)&dest_addr,
        sizeof(struct sockaddr));
时间: 2024-10-10 10:49:05

Linux - Socket网络套接字的相关文章

Linux Socket 原始套接字编程

对于linux网络编程来说,可以简单的分为标准套接字编程和原始套接字编程,标准套接字主要就是应用层数据的传输,原始套接字则是可以获得不止是应用层的其他层不同协议的数据.与标准套接字相区别的主要是要开发之自己构建协议头.对于原始套接字编程有些细节性的东西还是需要注意的. 1. 原始套接字创建 原始套接字的编程和udp网络编程的流程有点类似,但是原始套接字编程中不需要bind操作,因为在数据接收和发送过程中使用sendto和recvfrom函数实现数据的接收和发送.不过不是说原始套接字不能使用bin

Linux进程间通信 -- 数据报套接字 socket()、bind()、sendto()、recvfrom()、close()

前一篇文章,Linux进程间通信——使用流套接字介绍了一些有关socket(套接字)的一些基本内容,并讲解了流套接字的使用,这篇文章将会给大家讲讲,数据报套接字的使用. 一.简单回顾——什么是数据报套接字 socket,即套接字是一种通信机制,凭借这种机制,客户/服务器(即要进行通信的进程)系统的开发工作既可以在本地单机上进行,也可以跨网络进行.也就是说它可以让不在同一台计算机但通过网络连接计算机上的进程进行通信.也因为这样,套接字明确地将客户端和服务器区分开来. 相对于流套接字,数据报套接字的

什么是网络套接字(Socket)?

什么是网络套接字(Socket)?一时还真不好回答,而且网络上也有各种解释,莫衷一是.下文将以本人所查阅到的资料来说明一下什么是Socket. 1. Socket定义 Socket在维基百科的定义: A network socket is an endpoint of an inter-process communication across a computer network. Today, most communication between computers is based on t

APUE中网络套接字一章——使用pthread改写远程时间服务器

最近在看<Unix环境高级编程>一书,我一直对网络编程有兴趣,所以就直接跳到了网络套接字这一章. 这一章中有一个示例程序:一个TCP客户端向服务器发送连接请求,服务器在接受请求后,调用uptime命令 并将结果返回给客户端,客户端再将其打印出来. 因为前面刚看过线程那一章,所以我想把服务器改造成多线程的,以便同时服务多个线程.但是却碰到 一个问题,调试了半天还是没有进展(linux下调试我真的不是很会),google了下也没找到答案.索性先po 上来,整理下思路,如果有园子里的朋友能够帮忙解答

Linux编程设计——套接字

套接字 套接字,另外一种进程间通信的方式.之前的IPC机制只能限定在一台计算机系统上进行资源共享.而套接字接口可以使,一台机器上的进程和另外一个机器上的进程通信. 什么是套接字 套接字是一种通信机制,凭借这种机制,客户/服务器系统的工作即可以在本地单机上工作,也可以跨网络进行. 套接字和管道类型,同样是读写类文件描述符的操作.不同的是,套接字明确的将客户和服务器分开来.套接字机制可以实现多个客户连接一个服务器. 套接字连接 首先,服务器应用程序使用socket来创建一个套接字,它是系统分配给该服

linux socket网络编程 常用函数及头文件

转自:http://blog.chinaunix.net/u3/102500/showart_2065640.html 一 三种类型的套接字: 1.流式套接字(SOCKET_STREAM) 提供面向连接的可靠的数据传输服务.数据被看作是字节流,无长度限制.例如FTP协议就采用这种. 2.数据报式套接字(SOCKET_DGRAM) 提供无连接的数据传输服务,不保证可靠性. 3.原始式套接字(SOCKET_RAW) 该接口允许对较低层次协议,如IP,ICMP直接访问. 二 基本套接字系统调有有如下一

linux socket网络编程详解

一.系统调用和应用编程接口 在讨论网络通信之前, 首先明确两个概念:系统调用(system call) 和 应用编程接口(Application Programming Interface,API). 操作系统使用 系统调用 机制来实现 在应用程序 与 操作系统 之间进行控制权传递. 当某个应用进程启动了系统调用时,控制权就从应用程序传递给操作系统.操作系统执行某个内部过程之后,把控制权返回给应用程序. 对程序员来说,每一个系统调用和一般程序设计中的函数调用非常相似,只是系统调用是将控制权传递给

Win2 Socket(套接字)相关 API

Socket(套接字) 作者信息 肖进 单位:南京中萃食品有限公司 资讯部 邮箱:[email protected] 电话:025-58642091 与socket有关的一些函数介绍 1.读取当前错误值:每次发生错误时,如果要对具体问题进行处理,那么就应该调用这个函数取得错误代码. int  WSAGetLastError(void ); #define h_errno   WSAGetLastError() 错误值请自己阅读Winsock2.h. 2.将主机的unsigned long值转换为

学生党 应该去 研究研究 Socket(套接字) 实现原理

学生党 整天 不知所谓,    给你们 找点事 做做,     你们 可以去 研究一下 Socket (套接字) 的 实现原理, 看能不能 自己 实现一个  . Socket  是 操作系统 内核,  由 操作系统 直接调遣  .  为什么 是 操作系统 内核?  因为 Socket 涉及 到 IO,    IO 是 操作系统 的 基本任务, IO 涉及 中断, 所以必须作为 操作系统 内核,  由 操作系统 直接调度    . 多的也不要求了,     你们 去把  Windows Socke