现在,我们通过accept()创建了新的socket,也就是我们类中的数据成员communicationSock,现在,我们就可以通过这个socket进行通讯了。

       TCP通讯模型

       在介绍函数之前,我们应该了解一些事实。TCP的Server/Client模型类似这样:

       ServApp——ServSock——Internet——ClntSock——ClntApp

       当然,我们这里的socket指的就是用于“通讯”的socket。TCP的server端至少有两个socket,一个用于监听,一个用于通讯;TCP的server端可以只有一个socket,这个socket同时“插”在server的两个socket上。当然,插上listen socket的目的只是为了创建communication socket,创建完备后,listen是可以关闭的。但是,如果这样,其他的client就无法再连接上server了。

       我们这个模型,是client的socket插在server的communication socket上的示意。这两个socket,都拥有完整的本地地址信息以及远程计算机地址信息,所以,这两个socket以及之间的网络实际上形成了一条形式上“封闭”的管道。数据包只要从一端进来,就能知道出去的目的地,反之亦然。这正是TCP协议,数据流形式抽象化以及实现。因为不再需要指明“出处”和“去向”,对这样的socket(实际上是S/C上的socket对)的操作,就如同对本地文件描述符的操作一样。但是,尽管我们可以使用read()和write(),但是,为了完美的控制,我们最好使用recv()和send()。

       recv()和send()

C++代码
  1. int send(int socket, const void* msg, unsigned int msgLength, int flags);  
  2. int recv(int socket, void* rcvBuffer, unsigned int bufferLength, int flags);  

       在Linux中的实现为:

C++代码
  1. #include <sys/socket.h>  
  2.   
  3. /* Send N bytes of BUF to socket FD.  Returns the number sent or -1. 
  4.  
  5.    This function is a cancellation point and therefore not marked with 
  6.    __THROW.  */  
  7. extern ssize_t send (int __fd, __const void *__buf, size_t __n, int __flags);  
  8.   
  9. /* Read N bytes into BUF from socket FD. 
  10.    Returns the number read or -1 for errors. 
  11.  
  12.    This function is a cancellation point and therefore not marked with 
  13.    __THROW.  */  
  14. extern ssize_t recv (int __fd, void *__buf, size_t __n, int __flags);  

       这两个函数的第一个参数是用于“通讯”的socket,第二个参数是发送或者接收数据的起始点指针,第三个参数是数据长度,第四个参数是控制符号(默认属性设置为0就可以了)。失败时候传回-1,否则传回实际发送或者接收数据的大小,返回0往往意味着连接断开了。

       处理echo行为

C++代码
  1. void TcpServer::handleEcho()  
  2. {  
  3.     const int BUFFERSIZE = 32;  
  4.     char buffer[BUFFERSIZE];  
  5.     int recvMsgSize;  
  6.     bool goon = true;  
  7.   
  8.     while ( goon == true ) {  
  9.         if ( (recvMsgSize = recv(communicationSock, buffer, BUFFERSIZE, 0)) < 0 ) {  
  10.             throw "recv() failed";  
  11.         } else if ( recvMsgSize == 0 ) {  
  12.             goon = false;  
  13.         } else {  
  14.             if ( send(communicationSock, buffer, recvMsgSize, 0) != recvMsgSize ) {  
  15.                 throw "send() failed";  
  16.             }  
  17.         }  
  18.     }  
  19.   
  20.     close(communicationSock);  
  21. }  

       本小节最后要讲的函数是close(),它包含在<unistd.h>中

C++代码
  1. #include <unistd.h>  
  2.   
  3. /* Close the file descriptor FD. 
  4.  
  5.    This function is a cancellation point and therefore not marked with 
  6.    __THROW.  */  
  7. extern int close (int __fd);  

       这个函数用于关闭一个文件描述符,自然,也就可以用于关闭socket。

       下一小节是完整的源代码。默认的监听端口是5000。我们可以通过

       $telnet 127.0.0.1 5000

       验证在本机运行的echo server程序。

除非特别注明,鸡啄米文章均为原创
转载请标明本文地址:http://www.teaching4real.com/software/412.html
2015年7月24日
作者:鸡啄米 分类:软件开发 浏览: 注册送白菜网:0