您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 项目/工程管理 > Unix网络编程 4- TCP编程
Unix网络编程第四讲TCPsocket编程Unix和TCP/network的关系TCP的特点协议特点实现特点编程特点EthernetIP/NFTCP协议栈网卡LinuxKernel应用程序系统调用TCPSocketsProgramming创建一个被动模式的(server)socket.建立TCP连接.发送/接收数据.关闭连接.TCPC/S编程创建一个TCPsocketintsocket(intfamily,inttype,intproto);intsock;sock=socket(PF_INET,SOCK_STREAM,0);if(sock0){/*ERROR*/}绑定到有名地址intmysock;structsockaddr_inmyaddr;mysock=socket(PF_INET,SOCK_STREAM,0);myaddr.sin_family=AF_INET;myaddr.sin_port=htons(80);myaddr.sin_addr=htonl(INADDR_ANY);bind(mysock,(sockaddr*)&myaddr,sizeof(myaddr));建立被动模式的TCPsocket被动模式:地址已经确定.告诉内核接受到我(应用程序)的连接请求.3-wayhandshake告诉内核为我(应用程序)将到来的连接保存(排队)起来.listen()intlisten(intsockfd,intbacklog);sockfd-TCPsocket(已经绑定地址)backlog内核为应用程序缓冲到来连接的数目.listen()returns-1onerrorotherwise0.listeningsocket的两个队列接受连接请求accept()一旦调用了listen(),内核将替我们将带来的连接进行排队缓冲处理三次握手将多个连接排队缓冲.当我们的应用程序可以处理新的连接时,我们需要向内核请求下一个连接.accept()intaccept(intsockfd,structsockaddr*cliaddr,socklen_t*addrlen);sockfd是被动模式的TCPsocket.cliaddr指针,指向一个已分配好的空间.返回客户地址.addrlen是一个value-result参数必须设置为cliaddr的空间大小返回时,将被设置为使用cliaddr的空间大小.accept()返回值accept()返回一个新的socket描述符-1错误.一旦accept返回一个新的socket描述符,真正的数据I/O就可以进行了(在新的socket上read()和write()).read,writesocket的read()andwrite()操作和普通文件的有所不同!fread,fwrite缓冲的几种形式全缓冲行缓冲无缓冲标准输入、标准输出和标准出错stdin,fullbuffered,linebufferedifattystdout,fullbuffered,linebufferedifattystderr,nobuffered终结一个TCP连接连接的任意一方可以执行close()系统调用.和普通文件的close()一样,如果一个文件的引用数超过1,那么实际上该连接没有被终结;如果另外一端关闭了连接,并且本端没有缓冲数据,那么从TCPsocket读操作会返回0并指示EOF.ClientCodeTCP客户程序可以调用connect():负责建立客户程序socket的端地址.没有必要先调用bind,内核将负责给socket分配一个本地端地址(TCP端口,IP地址).试图和指定的服务器建立TCP连接.三次握手connect()intconnect(intsockfd,conststructsockaddr*server,socklen_taddrlen);sockfd是一个创建好的TCPsocket.server中有服务器的地址(IP地址和TCP端口号)connect()成功返回0,错误返回-1从TCPsocket读intread(intfd,char*buf,intmax);缺省情况下read()将阻塞一直到有数据为止.从一个TCPsocket一次read()操作的返回字节数可能max.你甚至得准备着一次只读取到1个字节的情况!向一个TCPsocket写入intwrite(intfd,char*buf,intnum);一次write()操作可能真正写入的字节数目少于num(如果是nonblockingsocket的话).书中有readn(),writen()和readline()等例程.几个有用的例程#includeunp.hssize_treadn(intfd,void*buff,size_tnbytes);ssize_twriten(intfd,constvoid*buff,size_tnbytes);ssize_treadline(intfd,void*buff,size_tmaxlen);返回值:读写字节数目,错误返回–1readn1#includeunp.h2ssize_t/*Readnbytesfromadescriptor.*/3readn(intfd,void*vptr,size_tn)4{5size_tnleft;6ssize_tnread;7char*ptr;8ptr=vptr;9nleft=n;10while(nleft0){11if((nread=read(fd,ptr,nleft))0){12if(errno==EINTR)13nread=0;/*andcallread()again*/14else15return(-1);16}elseif(nread==0)17break;/*EOF*/18nleft-=nread;19ptr+=nread;20}21return(n-nleft);/*return=0*/22}writen1#includeunp.h2ssize_t/*Writenbytestoadescriptor.*/3writen(intfd,constvoid*vptr,size_tn)4{5size_tnleft;6ssize_tnwritten;7constchar*ptr;8ptr=vptr;9nleft=n;10while(nleft0){11if((nwritten=write(fd,ptr,nleft))=0){12if(nwritten0&&errno==EINTR)13nwritten=0;/*andcallwrite()again*/14else15return(-1);/*error*/16}17nleft-=nwritten;18ptr+=nwritten;19}20return(n);21}readline1#includeunp.h3ssize_t/*PAINFULLYSLOWVERSION--exampleonly*/4readline(intfd,void*vptr,size_tmaxlen)5{6ssize_tn,rc;7charc,*ptr;8ptr=vptr;9for(n=1;nmaxlen;n++){10again:11if((rc=read(fd,&c,1))==1){12*ptr++=c;13if(c=='\n')14break;/*newlineisstored,likefgets()*/15}elseif(rc==0){16*ptr=0;17return(n-1);/*EOF,n-1byteswereread*/18}else{19if(errno==EINTR)20gotoagain;21return(-1);/*error,errnosetbyread()*/22}23}24*ptr=0;/*nullterminatelikefgets()*/25return(n);26}类比人际关系为了搞好人际关系:你需要主动做自我介绍.你需要学会开放的接受别人.你需要主动和别人建立联系.你需要学会别人给什么就接受什么,而不是你要什么别人给你什么.你需要当问题出现时及时处理好关系.一个TCP应用的例子echoclient从标准输入读取一行文字,发给server.server从网络读取输入,将读取到的一行文字返回给client.client读取反射回来的文字行,打印到标准输出.server1#includeunp.h2intmain(intargc,char**argv)4{5intlistenfd,connfd;6pid_tchildpid;7socklen_tclilen;8structsockaddr_incliaddr,servaddr;9listenfd=Socket(AF_INET,SOCK_STREAM,0);10bzero(&servaddr,sizeof(servaddr));11servaddr.sin_family=AF_INET;12servaddr.sin_addr.s_addr=htonl(INADDR_ANY);13servaddr.sin_port=htons(SERV_PORT);14Bind(listenfd,(SA*)&servaddr,sizeof(servaddr));15Listen(listenfd,LISTENQ);16for(;;){17clilen=sizeof(cliaddr);18connfd=Accept(listenfd,(SA*)&cliaddr,&clilen);19if((childpid=Fork())==0){/*childprocess*/20Close(listenfd);/*closelisteningsocket*/21str_echo(connfd);/*processtherequest*/22exit(0);23}24Close(connfd);/*parentclosesconnectedsocket*/25}26}1#includeunp.h2voidstr_echo(intsockfd)4{5ssize_tn;6charbuf[MAXLINE];7again:8while((n=read(sockfd,buf,MAXLINE))0)9Writen(sockfd,buf,n);10if(n0&&errno==EINTR)11gotoagain;12elseif(n0)13err_sys(str_echo:readerror);14}Echoclient1#includeunp.h2intmain(intargc,char**argv)4{5intsockfd;6structsockaddr_inservaddr;7if(argc!=2)8err_quit(usage:tcpcliIPaddress);9sockfd=Socket(AF_INET,SOCK_STREAM,0);10bzero(&servaddr,sizeof(servaddr));11servaddr.sin_family=AF_INET;12servaddr.sin_port=htons(SERV_PORT);13Inet_pton(AF_INET,argv[1],&servaddr.sin_addr);14Connect(sockfd,(SA*)&servaddr,sizeof(servaddr));15str_cli(stdin,sockfd);/*doitall*/16exit(0);17}str_cli()函数1#includeunp.h2voidstr_cli(FILE*fp,intsockfd)4{5charsendline[MAXLINE],recvline[MAXLINE];6while(Fgets(sendlin
本文标题:Unix网络编程 4- TCP编程
链接地址:https://www.777doc.com/doc-3398772 .html