Linux系统中常用的socket网络编程接口有:
- socket()
- bind()
- listen()
- accept()
- connect()
- send()
- recv()
- close()
- 其中connect()与send()为客户端专用接口;
- bind()、listen()、accept()及recv()为服务器端专用接口;
- socket()与close()则由服务器与客户端共用。
#includeint socket(int domain, int type, int protocol);
功能:创建套接字,类似于文件操作中的open函数。
参数说明:
- domain:指定通信域,选择通信时的协议族:
– AF_INET:网络通信;
– AF_UNIX:本地通信。 - type:指定socket的连接类型,其常用取值为:
– SOCK_STREAM:TCP协议;
– SOCK_DGRAM:UDP协议;
– SOCK_RAW:ICMP协议。 - protocol:一般设置为0,表示使用默认协议。
返回值说明:
- 成功:返回一个文件描述符,之后应用程序可以采用socket通信中的读写函数在网络中收发数据;
- 失败:返回-1,并设置errno。
#includeint bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen); struct sockaddr { sa_family_t sa_family; char sa_data[14]; //进程地址 }; //sockaddr的缺陷为:sa_data把目标地址和端口信息混在一起了 //sockaddr和sockaddr_in长度一样,都是16个字节,即占用的内存大小是一致的,因此可以互相转化。 //sockaddr和sockaddr_in是并列结构,指向sockaddr_in结构的指针也可以指向sockaddr。 #include struct sockaddr_in { short sin_family; unsigned short sin_port; struct in_addr sin_addr; unsigned char sin_zero[8]; }; typedef uint32_t in_addr_t; struct in_addr { in_addr_t s_addr; };
功能:
使服务器端的一个socket文件与网络中的一个进程进行绑定:
- 文件描述符可标识socket文件;
- “主机名+端口号”可标识网络中的唯一进程;
- bind函数实际上是将服务器端的socket文件与网络中的进程地址进程绑定。
参数说明:
- sockfd:socket文件的文件描述符,一般由socket()函数返回;
- addr:指代服务器的通信地址,其本质为struct sockaddr结构体类型的指针;
- addrlen:参数addr的长度,实质上addr参数可接受多种协议的结构体,而这些结构体的长度各不相同,因此需使用参数addrlen额外指定结构体长度。
例如:
struct sockaddr_in servaddr; //结构体定义 bzero(&servaddr, sizeof(servaddr)); //结构体清零 servaddr.sin_family = AF_INET; //设置地址类型为AF_INET servaddr.sin_addr.s_addr = htonl(INADDR_ANY); //设置网络地址为INADDR_ANY servaddr.sin_port = htons(85); //设置端口号为85
返回值说明:
- 成功:返回0;
- 失败:返回-1,并设置errno。
#includeint listen(int sockfd, int backlog);
功能:listen函数把一个未连接的套接字转换成一个被动套接字,指示内核应该接受指向该套接字的连接请求。
参数说明:
- sockfd:socket文件描述符;
- backlog:相应套接字请求队列的最大连接个数,也就是服务器同时可建立的最大连接数量。
返回值说明:
- 成功:0;
- 失败:返回-1,并设置errno。
#includeint accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
功能:accept函数在listen函数之后使用,其功能为阻塞等待客户端的连接请求。
当传输层使用TCP协议时,服务器与客户端在创建连接前,会先经过“三次握手”机制测试连接,“三次握手”完成后,服务器调用accept函数处理连接请求,此时若还没有客户端的请求到达,便阻塞等待调用accept函数的进程,直到接收到客户端发来的请求,且服务器中已创建的连接数未达到backlog,accept函数才会返回,并传出客户端的地址。
参数说明:
- sockfd:socket文件描述符;
- addr:传出参数,表示客户端的地址,当addr = NULL,表示不关心客户端的地址;
- addrlen:传入传出参数,传入是为函数调用提供参数addr的长度,传出时为客户端地址结构体的实际长度。
返回值说明:
- 成功:一个套接字,用于与本次通信的客户端进行数据交互;
- 失败:返回-1,并设置errno。
#includeint connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
功能:用于客户端,该函数的功能为向服务器发起连接请求。
- connect函数的参数与bind()函数中参数的形式一致;
- 区别在于bind中的参数为客户端进程地址,而connect的参数为服务器端地址。
参数说明:
- sockfd:socket文件描述符;
- addr:传入参数,表示要连接的服务器地址;
- addrlen:传入参数,为函数调用提供参数addr的长度。
返回值说明:
- 成功:0;
- 失败:返回-1,并设置errno。
#includessize_t send(int sockfd, const void *buf, size_t len, int flags);
功能:向处于连接状态的套接字中发送数据。
参数说明:
- sockfd:socket文件描述符;
- buf:指向要发送数据的缓冲区指针;
- len:缓冲区buf中数据的长度;
- flags:表示调用的执行方式(阻塞/非阻塞),通常设置为0。
// 下面的两个函数等效: write(sockfd, buf,len); send(sockfd, buf, len, 0);
Linux系统中还提供了sendto()函数和sendsg()函数,这两个函数不但能发送数据给已连接的套接字,还可向未连接的套接字发送数据。
#includessize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen); ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);
参数说明:
- sendto函数中的前4个参数与send()函数的参数相同,之后的参数dest_addr和addrlen分别用于设置接收数据进程的地址和地址的长度;
- sendmsg函数中的第二个参数msg为struct msghdr类型的结构体指针,该参数用于传入目标进程的地址、地址的长度等信息。
返回值说明:
- 成功:0;
- 失败:返回-1,并设置errno。
#includessize_t recv(int sockfd, void *buf, size_t len, int flags);
功能:用于从已连接的套接字中接收信息。
此外,read()函数、recvfrom()函数和recvmsg()函数也可用于接收信息。
参数说明:
- sockfd:socket文件描述符;
- buf:指向接收数据的缓冲区指针;
- len:缓冲区buf中数据的长度;
- flags:表示调用的执行方式(阻塞/非阻塞),通常设置为0。
返回值说明:
- 成功:返回读到的字节数;
- 失败:返回-1,并设置errno。
#includeint close(int fd);
功能:用于释放系统分配给套接字的资源。
参数说明:
- fd:socket文件描述符;
返回值说明:
- 成功:0;
- 失败:返回-1,并设置errno。



