您好,欢迎访问三七文档
当前位置:首页 > 电子/通信 > 综合/其它 > 第03章 TCP套接字基础
第3章TCP套接字基础2Socket基本概念理解套接字Socket电话通信网当进行电话通信时,必须建立一个具有两个端点的通信线路:•你的电话(在你的位置处)•对方的电话(在对方位置处)套接字代表通信线路中的端点3创建套接字#includesys/types.h#includesys/socket.hintsocket(intdomain,inttype,intprotocol);套接字的域名(domain),代表套接字地址族套接字的类型(types),最常用的两个值是SOCK_STREAM和SOCK_DGRAM使用的协议(protocol),一般情况下该参数为0,表示由系统在当前设定的domain下,自动选择适合的协议类型4域和地址族AF_UNIX,AF_LOCAL用于本地通信AF_INET,PF_INETIPv4,Internet协议AF_INET6IPv6,Internet协议AF_IPXNovell网络协议AF_X25ITU-TX.25/ISO-8208协议......5通用套接字地址结构#includesys/socket.hstructsockaddr{sa_family_tsa_family;charsa_data[14];}sa_familysa_data[14]2bytes6Internet套接字地址结构-1#includenetinet/in.hstructsockaddr_in{sa_family_tsa_family;uint16_tsin_port;structin_addrsin_addr;unsignedcharsin_zero[8];}structin_addr{uint32_ts_addr;}7Internet套接字地址结构-2sa_family=AF_INETsin_portsin_addrsin_zero[8]2bytes8远程主机信息函数#includenetdb.hstructhostent*gethostbyname(constchar*name);structhostent{char*h_name;/*主机的正式名称*/char**h_aliases;/*主机别名列表*/inth_addrtype;/*主机地址类型*/inth_length;/*地址长度*/char**h_addr_list;/*地址列表*/};/*保持后向兼容*/#defineh_addrh_addr_list[0]9流式套接字提供面向连接的,可靠的字节流服务面向连接意味着客户和服务器在进行实际数据传输前必须先建立一个TCP连接502010connection10数据报套接字提供无连接的,不可靠的服务当需要传输数据时不建立连接,直接向目标发送数据。50201050201011创建套接字#includesys/types.h#includesys/socket.hintsocket(intdomain,inttype,intprotocol);AF_INETSOCK_DGRAMSOCK_STREAM012绑定套接字#includesys/types.h#includesys/socket.hintbind(intsockfd,conststructsockaddr*localaddr,intlocaladdrlen);IP地址端口含义INADDR_ANY0内核选择IP地址和端口INADDR_ANY非0内核选择IP,应用确定端口本地IP0应用确定IP,内核选择临时端口本地IP非0应用选择IP和端口13流式套接字连接监听#includesys/types.h#includesys/socket.hintlisten(intsockfd,intbacklog);listen()将成功建立的连接入队列backlog队列accpet()read()并处理此请求客户端连接请求14流式套接字连接接收#includesys/types.h#includesys/socket.hintaccept(intlistenfd,conststructsockaddr*clientaddr,int*clientaddrlen);说明:lientaddr不是作为函数的传入参数,而是函数的返回参数如果该函数执行成功,它返回一个新的套接字描述符,称为连接套接字,服务器使用该套接字和已建立连接的客户端进行通信。而原有的监听套接字可以继续接收后续新客户的连接请求。15流式套接字连接发起#includesys/types.h#includesys/socket.hintconnect(intsockfd,conststructsockaddr*serveraddr,intserveraddrlen);ETIMEDOUT,若客户端TCP在发出首个SYN分段后没有收到任何应答,则大约在调用connect()函数75秒后将返回该错误ECONNREFUSED,当服务器进程并未启动,此时客户端TCP将向客户端应用返回该错误EHOSTUNREACH或ENETUNREACH,若客户端TCP发出的SYN分段收到了途经的中间路由器的“目标不可达”ICMP报文,则客户端TCP会重发SYN分段直到超过75秒,此时客户端TCP向客户端应用返回该错误16读流式套接字#includeunistd.hintread(intsockfd,constvoid*buf,intbuflen);buf,读入数据的缓冲区,buflen为其长度,代表本次读的最大数据长度函数返回值,实际所读取的数据字节长度,0表示读到文件尾,-1表示错误17写流式套接字#includeunistd.hintwrite(intsockfd,constvoid*buf,intbuflen);buf为写数据的缓冲区,buflen为其长度函数返回值为实际所写的数据字节长度,-1表示错误18关闭流式套接字#includeunistd.hintclose(intsockfd);intshutdown(intsockfd,inthow);值宏说明0SHUT_RD不允许本地socket进行读操作1SHUT_WR不允许本地socket进行写操作2SHUT_RDWR不允许本地socket进行读和写操作(等于close)how的取值及含义19TCP流式套接字通信模式服务器socket()bind()listen()accpet()read()write()close()socket()connect()write()read()客户机close()子进程实现TCP套接字编程实现TCP套接字分为:服务器端和客户端两部分服务器端①创建套接字②绑定套接字③设置套接字为监听模式,进入被动接受连接状态④接受请求,建立连接⑤读写数据⑥终止连接实现TCP套接字编程客户端步骤①创建套接字②与远程服务器建立连接③读/写数据;④终止连接TCP服务器模板intmain(void){intsockfd,connect_sock;if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1){perror(“createsocketfailed.”);exit(-1);}/*bindsockfdtosomeaddress*//*listen*/……loop{if((connect_sock=accept(sockfd,NULL,NULL))==-1){perror(“Accepterror.”);exit(-1);}/*readandprocessrequest*/close(connect_sock);}close(sockfd);}TCP客户模板/*includesomeheaderfiles*/intmain(void){intsockfd;if((sockfd=socket(AF_INET,SOCK_STREAM,0))=-1){perror(“Createsocketfailed.”);exit(-1);}/*connecttoserver*/……/*sendrequstandreceiveresponse*/……close(sockfd);}TCP套接字编程实例采用客户/服务器模式,完成下列功能:客户根据用户提供的IP地址,连接相应的服务器;服务器等待客户的连接,一旦连接成功,则显示客户的IP地址,并发欢迎信息给客户;客户接收服务器发送的信息并显示;服务器三种异常情况下面我们考虑在以下三种异常情况发生后,tcp客户/服务器程序的反映;服务器主机崩溃服务器主机崩溃后重启服务器主机关机。服务器主机崩溃服务器主机崩溃时,已有的网络连接上发不出任何东西。同时假设应用程序发出数据后,然后阻塞于从套接字读取响应。由于服务器主机崩溃,因此客户tcp会持续重传数据分节,试图从服务器接收一个ACK:源自Berkeley的实现将重传12次。当客户tcp最终放弃时,返回给客户一个错误,此时错误是ETIMEDOUT,或者是因为中间路由器判定服务器主机不可达,且以一个目的地不可达的ICMP消息响应,则错误是EHOSTUNREACH或ENETUNREACH。通过设置套接字选项可以更改tcp持续重传等待的超时时间。服务器主机崩溃后重启在这种情况下,如果客户在主机崩溃重启前不主动发送数据,那么客户是不会知道服务器已崩溃的。在服务器重启后,客户向服务器发送一个数据分节;由于服务器重启后丢失了以前的连接信息(尽管在服务端口上有进程监听,但连接套接字所在的端口无进程等待),因此导致服务器主机的tcp响应RST;当客户tcp收到RST,向客户返回错误,ECONNRESET如果客户对服务器的崩溃情况很关心,即使客户不主动发送数据也这样,就需要其他技术支持(如套接口选项SO_KEEPALIVE或某些客户/服务器心跳函数)。服务器主机关机当Linux主机关机时,由init进程给所有运行的进程发信号SIGTERM(我们的服务器程序可以捕获该信号,并在信号处理程序中正常关闭网络连接)。如果服务器程序忽略了SIGTERM信号,则init进程会等待一段固定的时间(通常是5s~20s),然后给所有还在运行的程序发信号SIGKILL(该信号不能由服务器程序捕获);服务器将由信号SIGKILL终止,其终止时,所有打开的描述字被关闭,这导致向客户发送FIN分节;客户收到FIN分节后,能推断出服务器将终止服务。
本文标题:第03章 TCP套接字基础
链接地址:https://www.777doc.com/doc-3394092 .html