TCP套接字函数
程序员文章站
2022-07-14 20:46:09
...
1. socket函数
#include <sys/socket.h>
int socket(int family, int type, int protocol);
//若成功则返回非负描述符
//若出错返回-1
2.connect函数
#include <sys/socket.h>
int connect(int sockfd, const struct sockaddr* servaddr, socklen_t addrlen);
//若成功则返回0,出错返回-1
-
第二个参数是一个指向套接字地址结构的指针。
-
客户再调用函数connect前不必非得调用bind函数。
-
调用connect函数将激发TCP的三路握手,而且仅在连接建立成功或出错时才返回。
出错情况: (1)TCP客户端没有收到SYN分节的响应,返回ETIMEDOUT (2)若对SYN的响应为RST,表明服务器在指定端口没有进程在等待连接。 (3)SYN在中间某个路由器引发“目的地不可达”的ICMP错误。
-
若connect失败则该套接字不再可用,必须关闭。
3.bind函数
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *myaddr, aocklen_t addrlen);
//若成功则为0,出错返回-1
- 若指定端口号0,内核就会在bind被调用时选择一个临时端口。
- 若指定IP地址为通配地址,则内核将等到套接字已连接(TCP)时才选择一个IP地址。
- 对于IPv4,通配地址由常值INADDR_ANY指定,其值一般为0。
struct sockaddr_in servaddr;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
- 若让内核为套接字选择一个临时端口号,bind并不返回所选择的值。为了得到内核所选择的临时端口值,必须调用getsockname()函数。
4.listen函数
#include <sys/socket.h>
int listen(int sockfd, int backlog);
//若成功则为0,出错返回-1
-
第二个参数规定了内核应该为相应套接字排队的最大连接个数。
内核为任何一个给定的监听套接字维护两个队列 (1)未完成连接队列,已由客户发出SYN并到达服务器,而服务器正等待完成相应的三路握手。 (2)已完成连接队列,每个已完成三路握手对应其中一项。 (3)两队列之和不超过backlog。
- 当进程调用accept时,已完成连接队列中的对头项将返回给进程。
- 指定一个比内核能够支持的值还要大的backlog也是可以接受的,内核会做相应的截短。
- 当一个客户SYN到达时,若队列是满的,TCP就忽略该分节,不发送RST。
5.accept函数
#include <sys/socket.h>
int accept(int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen);
- 函数的第一个套接字为监听套接字,其返回值为已连接套接字。
6.close函数
#include <sys/socket.h>
int close(int sockfd);
//成功则返回0,出错返回-1
-
调用该函数会发生FIN分节,随后是正常的TCP连接终止序列。
-
TCP将尝试发送已排队等待发送到对端的任何数据,发送完毕后是正常的TCP连接终止序列。
父进程关闭已连接套接字只是导致相应描述符的引用计数值减1,若我们确实想在某个TCP连接上发送一个FIN,可以调用shutdown函数。
7.getsockname()和getpeername()
#include <sys/socket.h>
int getsockname(int sockfd, struct sockaddr *localaddr, socklen_t *addrlen);
int getpeername(int sockfd, struct sockaddr *peeraddr, socklen_t *addrlen);
-
在一个没有调用bind的TCP客户,connect成功返回后,getsockname用于返回由内核赋予该连接的本地IP地址和本地端口号。
-
在以端口号0调用bind后,getsockname返回由内核赋予的本地端口号。
-
在一个以通配IP地址调用bind的服务器,与某个客户的连接一旦建立(accept返回),getsockname就可以用于返回内核赋予该连接的本地IP地址。
下一篇: JavaEye生物多样性群落的思考