随笔 - 96  文章 - 255  trackbacks - 0
<2008年7月>
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789

E-mail:zbln426@163.com QQ:85132383 长期寻找对战略游戏感兴趣的合作伙伴。

常用链接

留言簿(21)

随笔分类

随笔档案

SDL相关网站

我的个人网页

我的小游戏

资源下载

搜索

  •  

积分与排名

  • 积分 - 485043
  • 排名 - 37

最新评论

阅读排行榜

评论排行榜

作者:龙飞

        现在,我们通过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()
int send(int socket, const void* msg, unsigned int msgLength, int flags);
int recv(int socket, void* rcvBuffer, unsigned int bufferLength, int flags);
在Linux中的实现为:
#include <sys/socket.h>

/* Send N bytes of BUF to socket FD.  Returns the number sent or -1.

   This function is a cancellation point and therefore not marked with
   __THROW.  
*/
extern ssize_t send (int __fd, __const void *__buf, size_t __n, int __flags);

/* Read N bytes into BUF from socket FD.
   Returns the number read or -1 for errors.

   This function is a cancellation point and therefore not marked with
   __THROW.  
*/
extern ssize_t recv (int __fd, void *__buf, size_t __n, int __flags);
这两个函数的第一个参数是用于“通讯”的socket,第二个参数是发送或者接收数据的起始点指针,第三个参数是数据长度,第四个参数是控制符号(默认属性设置为0就可以了)。失败时候传回-1,否则传回实际发送或者接收数据的大小,返回0往往意味着连接断开了。

处理echo行为
void TcpServer::handleEcho()
{
    
const int BUFFERSIZE = 32;
    
char buffer[BUFFERSIZE];
    
int recvMsgSize;
    
bool goon = true;

    
while ( goon == true ) {
        
if ( (recvMsgSize = recv(communicationSock, buffer, BUFFERSIZE, 0)) < 0 ) {
            
throw "recv() failed";
        } 
else if ( recvMsgSize == 0 ) {
            goon 
= false;
        } 
else {
            
if ( send(communicationSock, buffer, recvMsgSize, 0!= recvMsgSize ) {
                
throw "send() failed";
            }
        }
    }

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

/* Close the file descriptor FD.

   This function is a cancellation point and therefore not marked with
   __THROW.  
*/
extern int close (int __fd);
这个函数用于关闭一个文件描述符,自然,也就可以用于关闭socket。
下一小节是完整的源代码。默认的监听端口是5000。我们可以通过
$telnet 127.0.0.1 5000
验证在本机运行的echo server程序。
posted on 2008-07-16 12:26 lf426 阅读(8105) 评论(2)  编辑 收藏 引用 所属分类: SDL入门教程Linux与C++socket 编程入门教程

FeedBack:
# re: socket 编程入门教程(一)TCP server 端:7、接收与发送 2010-10-16 16:43 莉萨
楼主有笔误哦. TCP通讯模型第二段:

TCP 的server端可以只有一个socket,这个socket同时“插”在server的两个socket上。

这里应该是: TCP的 client端可以只有一个......  回复  更多评论
  
# re: socket 编程入门教程(一)TCP server 端:7、接收与发送 2010-10-16 16:50 莉萨
这段貌似没有前几段写的详细了呢...在描述send 和recv函数中有这样一句话:

"这两个函数的第一个参数是用于“通讯”的socket"

这里的"通讯"这个词是否指的是destination 的socket呢?
改为"被叫端"是否更妥当呢?如果client和server都进行send和recv的,"通讯"这个词就不能很清楚的说明楼主想表达的意思了呢.  回复  更多评论
  

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理