第03章+基本TCP套接口编程

上传人:夏** 文档编号:569320182 上传时间:2024-07-28 格式:PPT 页数:29 大小:167.50KB
返回 下载 相关 举报
第03章+基本TCP套接口编程_第1页
第1页 / 共29页
第03章+基本TCP套接口编程_第2页
第2页 / 共29页
第03章+基本TCP套接口编程_第3页
第3页 / 共29页
第03章+基本TCP套接口编程_第4页
第4页 / 共29页
第03章+基本TCP套接口编程_第5页
第5页 / 共29页
点击查看更多>>
资源描述

《第03章+基本TCP套接口编程》由会员分享,可在线阅读,更多相关《第03章+基本TCP套接口编程(29页珍藏版)》请在金锄头文库上搜索。

1、Tcp套接字编程TCP套接字编程(cont.)基本套接字函数socket#include int socket(int family, int type, int protocol) 返回:非负套接字(sockfd)成功;-1出错。family:协议族;type:套接字类型; protocol:一般为0,除原始套接字外。 family typeAF_INET IPv4协议SOCK_STREAM 字节流套接口AF_INET6IPv6协议SOCK_DGRAM 数据报套接口AF_LOCALunix域协议SOCK_RAW 原始套接口AF_ROUTE 路由套接口AF_KEY 密钥套接口Protocol:

2、指明此socket请求所使用的协议,可以使用如下相关符号常数来表示。IPPROTO_TCP:表示TCP协议IPPROTO_UDP:表示UDP协议基本套接字函数bind#include int bind(int sockfd, const struct sockaddr *addr, socklen_len len) 返回:0成功;-1出错并置errnon该函数指明套接字将使用本地的哪一个协议端口进行数据传送(IP地址和端口号),注意:协议地址addr是通用地址。nLen是该地址结构(第二个参数)的长度。n一般而言,服务器调用此函数,而客户则很少调用它。 绑定地址时,可以指定地址和端口号,也可以

3、指定其中之一,甚至一个也不指定。通配地址:INADDR_ANY,其值一般为0,它通知内核选择IP地址。IP地址 端口 结果通配地址 0 内核选择IP地址和端口号通配地址 非0 内核选择IP地址,进程指定端口本地IP 0 进程指定IP地址,内核选择端口本地IP 非0 进程指定IP地址和端口号 若指定端口号为0,调用函数bind时,内核选择一个临时端口(在实际中,端口号都要指定);但若指定一个通配IP地址,则直到套接字已连接(TCP)或数据报已在套接字上发出(UDP),内核才选择一个本地IP地址。bind函数的用法struct sockaddr_in addr;int port = 1234;in

4、t opt = SO_REUSEADDR;setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt); bzero(&server,sizeof(server);addr.sin_family = AF_INET;addr.sin_addr.s_addr = htonl(INADDR_ANY);addr.sin_port = htons(port);if (bind(fd, (struct sockaddr *)&addr, sizeof(addr) = -1)/* 错误处理 */基本套接字函数listen#include int li

5、sten(int sockfd, int backlog) 返回:0成功;-1出错并置errno值;n函数listen仅被服务器调用,它完成两件事情:n函数listen将未连接的套接字转化成被动套接字,指示内核应接受指向此套接字的连接请求;n函数的第二个参数规定了内核为此套接字排队的最大连接个数;n对于给定的监听套接字,内核要维护两个队列n未完成连接队列n已完成连接队列n两个队列之和不超过backlog;客户服务器Connect调用在未完成队列建立条目SYN JSYN K, ack J+1ack K+1该条目从未完成队列移至已完成队列,accept阻塞Connect返回TCP三路握手和监听套接

6、口的两个队列listen函数(续)三路握手完成两队列之和不能超过backlog已完成连接队列(ESTABLISHED状态)未完成连接队列(SYN_RCVD状态)新到达的SYN分节服务器TCPacceptTCPTCP为监听套接口维护的两个队列为监听套接口维护的两个队列listen函数(续)另外几点说明:n不同的实现对backlog有不同的解释,如源自Berkeley的实现将backlog增加一个模糊因子,把它乘以1.5,再作为两个队列之和;n不要把backlog定义为0,因为有些实现允许1个连接排队,而有些实现不允许有连接排队;n当一个客户SYN到达时,若两个队列都是满的,tcp就忽略此分节,且

7、不发送RST。这是因为,这种情况是暂时的,客户tcp将重发SYN,期望不久的将来就能在队列中找到空闲条目。n n如果发送如果发送RSTRST,将会出现?将会出现?基本套接字函数connect#include int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen); 返回:0成功;-1出错;n函数connect激发TCP的三路握手过程;仅在成功或出错返回;错误有以下几种情况:n如果客户没有收到SYN分节的响应(总共75秒,这之间需要可能需要重发若干次SYN),则返回ETIMEDOUT。n如果对客户的SYN的响

8、应是RST,则表明该服务器主机在指定的端口上没有进程在等待与之相连。函数返回错误ECONNREFUSED;n如果客户发出的SYN在中间路由器上引发一个目的地不可达ICMP错误,客户上的内核保存此消息,并按第一种情况,连续发送SYN,直到规定时间,返回保存的消息(即ICMP错误)作为EHOSTUNREACH或ENETUNREACH错误返回给进程。基本套接字函数accept#include int accept(int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen); 返回:非负描述字(connfd)OK;-1出错;naccept函数由T

9、CP服务器调用;从已完成连接队列头返回下一个已完成连接;如果该队列空,则进程进入睡眠状态。n函数返回的套接字为已连接套接字,应与监听套接字区分开来n该函数最多返回三个值返回三个值:一个既可能是新套接字也可能是错误指示的整数,一个客户进程的协议地址(由cliaddr所指),以及该地址的大小(这后两个参数是值结果参数);也就是说,服务器可以通过参数cliaddr来得到请求连接并获得成功的客户的地址和端口号;基本套接字函数close#include int close(int sockfd); 返回:0OK;-1出错;nclose函数缺省功能是将套接字做上“已关闭”标记,并立即返回到进程。这个套接字

10、不能再为该进程所用。n正常情况下,close将引发向TCP的四分节终止序列,但在终止前将发送已排队的数据;n如果套接字描述符访问计数在调用close后大于0(在多个进程共享同一个套接字的情况下),则不会引发TCP终止序列(即不会发送FIN分节);基本套接字函数-shutdown#include int shutdown(int sockfd, int howto); 返回:0OK;-1出错,并置相应的errno的值;n该函数立即发送FIN分节(无论其访问计数是否大于0)。shutdown根据参数howto关闭指定方向的数据传输;nSHUT_RD:关闭连接的读这一半,不再接收套接字中的数据且现留

11、在接收缓冲区的数据作废;nSHUT_WR :关闭连接的写这一半(半关闭),当留在套接字发送缓冲区中的数据都被发送,后跟tcp连接终止序列,不管访问计数是否大于0;此后将不能在执行对套接字的任何写操作;nSHUT_RDWR:连接的读、写都关闭,这等效于调用shutdown两次,一次调用是用SHUT_RD,第二次用SHUT_WR。数据数据FIN数据和FIN的确认数据数据FIN数据和FIN的确认writewriteshutdownRead返回大于0Read返回大于0Read返回0writewritecloseRead返回大于0Read返回0Read返回大于0客户服务器调用shutdown关闭一半TC

12、P连接基本套接字函数read#include int read(int fd, char *buf, int len);返回:大于0读写字节大小;-1出错;n调用函数read时,有如下几种情况:n套接字接收缓冲区接收数据,返回接收到的字节数;ntcp协议收到FIN数据,返回0;ntcp协议收到RST数据,返回1,同时errno为ECONNRESET;n进程阻塞过程中接收到信号,返回1,同时errno为EINTR。read(connfd,buff,strlen(buff);基本套接字函数write#include int write(int fd, char *buf, int len); 返回

13、:大于0读写字节大小;-1出错;n调用函数write,有如下几种情况:n套接字发送缓冲区有足够空间,返回发送的字节数;ntcp协议接收到RST数据,返回1,同时errno为ECONNRESET; ;n进程阻塞过程中接收到信号,返回1,同时errno为EINTR。write(connfd,buff,strlen(buff);数据传输函数send#include #include ssize_t send (int fd, const void *msg, size_t len, int flags); 返回:非0发送成功的数据长度;-1出错;nflags 是传输控制标志,其值定义如下:n0:常规

14、操作,如同write()函数nMSG_OOB,发送带外数据(TCP紧急数据)。nMSG_DONTROUTE:忽略底层协议的路由设置,只能将数据发送给与发送机处在同一个网络中的机器上。数据传输函数recv#include #include ssize_t recv(int fd, void *buf ,size_t len, int flags); 返回:大于0表示成功接收的数据长度;0: 对方已关闭,-1:出错。nflags是传输控制标志,其值定义如下:n0:常规操作,如同read()函数;nMSG_PEEK:只查看数据而不读出数据,后续读操作仍然能读出所查看的该数据;nMSG_OOB:忽略常

15、规数据,而只读带外数据;nMSG_WAITALL:recv函数只有在将接收缓冲区填满后才返回。TCP套接字编程n实现TCP套接字基本步骤分为服务器端和客户端两部分:n服务器端创建套接字;绑定套接字;设置套接字为监听模式,进入被动接受连接状态;接受请求,建立连接读写数据终止连接TCP套接字编程(cont.)n客户端步骤创建套接字与远程服务器建立连接读/写数据;终止连接TCP服务器模板int main(void)int sockfd,connect_sock;if(sockfd=socket(AF_INET,SOCK_STREAM,0)=-1) perror(“create socket fail

16、ed.”);exit(-1);/* bind sockfd to some address */* listen */loop if(connect_sock=accept(sockfd,NULL,NULL)=-1) perror(“Accept error.”); exit(-1); /* read and process request */close(connect_sock); close(sockfd);TCP客户模板/* include some header files */int main(void)int sockfd;if(sockfd=socket(AF_INET,SOC

17、K_STREAM,0)=-1)perror(“Create socket failed.”);exit(-1);/* connect to server */* send requst and receive response */close(sockfd);TCP套接字例程n采用客户/服务器模式,完成下列功能:n客户根据用户提供的IP地址,连接相应的服务器;n服务器等待客户的连接,一旦连接成功,则显示客户的IP地址,并发欢迎信息给客户;n客户接收服务器发送的信息并显示;三种异常情况n下面我们考虑在以下三种异常情况发生后,tcp客户服务器程序的反映;n服务器主机崩溃n服务器主机崩溃后重启n服务

18、器主机关机。服务器主机崩溃n服务器主机崩溃时,已有的网络连接上发不出任何东西。n同时假设应用程序发出数据后,然后阻塞于从套接字读取响应。n由于服务器主机崩溃,因此客户tcp会持续重传数据分节,试图从服务器接收一个ACK:源自Berkeley的实现将重传12次。当客户tcp最终放弃时,返回给客户一个错误,此时错误是ETIMEDOUT,或者是因为中间路由器判定服务器主机不可达,且以一个目的地不可达的ICMP消息响应,则错误是EHOSTUNREACH或ENETUNREACH。n通过设置套接字选项可以更改tcp持续重传等待的超时时间。服务器主机崩溃后重启n在这种情况下,如果客户在主机崩溃重启前不主动发

19、送数据,那么客户是不会知道服务器已崩溃的。在服务器重启后,客户向服务器发送一个数据分节;n由于服务器重启后丢失了以前的连接信息(尽管在服务端口上有进程监听,但连接套接字所在的端口无进程等待),因此导致服务器主机的tcp响应RST;n当客户tcp收到RST,向客户返回错误,ECONNRESETn如果客户对服务器的崩溃情况很关心,即使客户不主动发送数据也这样,就需要其他技术支持(如套接口选项SO_KEEPALIVE或某些客户服务器心跳函数)。服务器主机关机n当Linux主机关机时,由init进程给所有运行的进程发信号SIGTERM(我们的服务器程序可以捕获该信号,并在信号处理程序中正常关闭网络连接)。n如果服务器程序忽略了SIGTERM信号,则init进程会等待一段固定的时间(通常是5s20s),然后给所有还在运行的程序发信号SIGKILL(该信号不能由服务器程序捕获);服务器将由信号SIGKILL终止,其终止时,所有打开的描述字被关闭,这导致向客户发送FIN分节;n客户收到FIN分节后,能推断出服务器将终止服务。

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 建筑/环境 > 施工组织

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号