Welcome 微信登录

首页 / 操作系统 / 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错误。