首页 / 操作系统 / Linux / Linux TCP协议的基础编程模型
一、TCP协议的基础编程模型TCP是面向连接的通信协议,采用客户机-服务器模式。套接字的全部工作流程如下所述:1.服务器启动进程,调用Socket创建一个基于TCP协议的流套接字描述符。2.其次,服务进程调用bind命名套接字,将套接字描述符绑定到本地地址和本地端口上,至此Socket的半相关描述---{协议,本地地址,本地端口}---完成。3.再次,服务器端调用listen,开始侦听客户端的Socket连接请求。4.接下来,客户端创建套接字描述符,并且调用connect向服务端提交连接请求。服务器端接收到客户端连接请求后,调用accept接受,并创建一个新的套接字描述符与客户端建立连接,然后原套接字描述符继续侦听客户端的连接请求。5.客户端与服务器端的新套接字进行数据传送,调用write或send向对方发送数据,调用read或recv接收数据。6.在数据交流完毕后,双方调用close或者shutdown半闭套接字。
二、UNIX基于TCP的通信相关函数1.Socket的创建---系统调用Socket #include<sys/types.h> #include<sys/socket.h> int socket(int domain, int type, int protocol); 返回值:成功返回创建的套接字描述符,否则返回-1并置errno。 说明:函数socket创建一个Socket描述符。 domain 指定发送通信的域,即套接字的协议族。有AF_UNIX(本地主机通信)和AF_INET(Internet地址IPV4协议)。 type 指定通信类型,有SOCK_STREAM,SOCK_DGRAM和SOCK_RAW。 Protocol指定了该套接字描述符上的一个特殊的协议书,比如TCP、UDP等,一般设置为0。2.Socket的命名---系统调用bind #include<sys/types.h> #include<sys/socket.h> int bind(int s, const struct sockaddr *name, int namelen); 返回值:成功返回0,否则返回-1并置errno。 函数bind命名一个套接字,它为该套接字描述符分配一个半相关属性。 s 调用socket创建的套接字。 指针name指向通用套接字的协议地址结构,包括协议、地址和端口信息等。 namelen 指定该协议地址结构长度,一般定义为sizeof(sockaddr_in)。 关于套接字地址属性结构: struct sockaddr{ u_short sa_family; /* 协议族 */ char sa_data[14]; /* 最多14字节的协议地址 */ }; 不同的协议有不同的地址描述方式,为了便于编码处理,每种协议族都定义了自己的套接字地址属性结构,比如协议族AF_INET使用结构sockaddr_in描述套接字地址信息,该结构定义在头文件<netinet/in.h>中。 struct sockaddr_in{ short sin_family; /* 16位的地址协议族(AF_INET)*/ u_short sin_port; /* 16位的端口地址 */ struct in_addr sin_addr; /* 32位的IP地址 */ char sin_zero[8]; /* 预留 */ }; struct in_addr{ u_long s_addr; }; 预留成员作用是使结构sockaddr_in与结构sockaddr的长度相同。 IP地址转换---完成IP地址的字符串格式与32位4字节整型之间的转换。 unsigned long inet_addr(char *ptr); int inet_aton(char *ptr, stuct in_addr *addrptr); char *inet_ntoa(struct in_addr inaddr); 字节顺序转换---实现主机字节顺序与网络字节顺序之间转换 #include<sys/types.h> #include<netinet/in.h> u_short htons(u_short hostshort); /*将16位整数由主机字节顺序转换成网络字节顺序*/ u_long htonl(u_long hostlong); /*将32位整数由主机字节顺序转换成网络字节顺序*/ u_short ntohs(u_short netshort); /*将16位整数由网络字节顺序转换成主机字节顺序*/ u_long ntohl(u_long netlong); /*将32位整数由网络字节顺序转换成主机字节顺序*/ 例:命名套接字描述符s的协议为AF_INET,地址为“127.0.0.1”,端口号为1000。 struct sockaddr_in sockaddr1; /*申请地址结构空间*/ memset(&sockaddr1, 0 , sizeof(sockaddr1)); /*清空空间*/ sockaddr1.sin_family = AF_INET; sockaddr1.sin_addr.s_addr = inet_addr(“127.0.0.1”); /*IP地址转换为整型赋值*/ sockaddr1.sin_port = htons(1000); /*端口号 主机字节顺序转换为网络字节顺序*/ 如需系统自动指定套接字的IP地址,则 sockaddr1.sin_addr.s_addr = htonl(INADDR_ANY); /*自动分配地址*/3.Socket的侦听---系统调用listen #include<sys/types.h> #include<sys/socket.h> int listen(int s, int backlog); 返回值:成功返回0,否则返回-1并置errno。 TCP服务器端必须调用listen函数才能使套接字进入侦听状态。 s 调用socket创建、bind命名的套接字。 backlog 确定套接字s接收的最大数目,如果到达最大的连接数,服务器端将向客户端发出ECONNRERUSED错误。