多clinet的C/S程序设计

(摘抄自: TCP/IP 应用程序的通信连接模式 http://www.ibm.com/developerworks/cn/aix/library/0807_liugb_tcpip/index.html)
(注:代码实现可以在这里找到 http://blog.csdn.net/mythfish/archive/2008/11/17/3321789.aspx
一、连接建立
(1)利用一个clinet连接一个server形式多client连接
server轮流使用多个端口建立与client的连接,连接关闭后立即释放端口。server针对每一个client连接一个专门的进程来处理,由于端口有限,server用一个循环来处理每个可用的端口,新端口需要bind()来绑定,所以从bing开始到close是一个循环体。

(2)使用多个accept实现多个client连接
多accept的server也只有一个socket,一个bind,一个listen。它建立许多工作子进程,每个子进程都有accept,这样可以为每个client建立socket描述符。循环体从accept开始到close结束。

(3)并发的server模式实现多client连接
accept之后fork一个子进程。socket会产生listenfd(socket描述符),accept会产生connfd。连接建立后子进程继承连接描述符服务于client,父进程则继续使用listenfd等待另外一个client的连接,以产生另外一个connfd和子进程。并发服务器支持的最大client数有listen的第二个参数决定。

(4)使用I/O多路技术实现多client连接
采用一个线程处理多个文件描述符的方式。I/O多路技术采用select或poll系统调用实现,select和poll功能相同,但poll可以更少使用内存资源以及更少的错误产生。select系统调用可以使一个进程检测多个等待的I/O是否准备好,当设备没准备好时,select处于阻塞状态,其中一个准备好后select返回,同时select会在等待一个超时时间后返回。在listen和accept之间插入select调用,使用三个宏FD_ZERO(),FD_CLR(),FD_SET(),在调用select前设置socket描述符屏蔽位,在select返回后使用FD_ISSET()来检测socket描述符集中对应的socket描述符位是否被设置。如果被设置则可以进行读写通信操作。

二、通信连接方式
通信的连接方式主要有短连接和长连接
(1)短连接通信指client方与server方每次通信报文收发时建立通讯连接,交易完成后立即断开。

(2)长连接通信,连接建立后为多次数据报交易服务。长连接下,需要循环读写通信数据。为区分每次的通信数据,需要在数据头指定数据的长度。

三、通信发送和接收方式设计
(1)同步发送接收
报文发送后需要等待接收方返回消息报文。同步方式需要考虑超时问题。同步方式一般与短连接通信结合使用。
(2)异步发送与接收
发送方只管发送数据,接收方只顾接收数据。通常,发送和接收在两个不同的进程处理,一般与长连接通信结合使用。
(3)异步双工
两个不同的子进程分别负责发送和接收,server与client分别fork两个进程,形成两个连接,两个连接都是单向的,一个接收,另一个发送。

(4)异步单工
两个不同的程序分别负责发送和接收,两个应用程序依靠应用逻辑来实现。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
客户端和服务端 网络程序和普通的程序有一个最大的区别是网络程序是由两个部分组成的--客户端和服务器端. 客户端 在网络程序中,如果一个程序主动和外面的程序通信,那么我们把这个程序称为客户端程序。 比如我们使用ftp程序从另外一 个地方获取文件的时候,是我们的ftp程序主动同外面进行通信(获取文件), 所以这个地方我们的ftp程序就是客户端程序。 服务端 和客户端相对应的程序即为服务端程序。被动的等待外面的程序来和自己通讯的程序称为服务端程序。 比如上面的文件获取中,另外一个地方的程序就是服务端,我们从服务端获取文件过来。 [代码] [C/C++]代码 /******* 服务器程序 (server.c) ************/ #include #include #include #include #include #include #include #include #include #include int main(int argc, char *argv[]) { int sockfd,new_fd; struct sockaddr_in server_addr; struct sockaddr_in client_addr; int sin_size,portnumber; char hello[]="Hello! Are You Fine?\n"; if(argc!=2) { fprintf(stderr,"Usage:%s portnumber\a\n",argv[0]); exit(1); } if((portnumber=atoi(argv[1]))<0) { fprintf(stderr,"Usage:%s portnumber\a\n",argv[0]); exit(1); } /* 服务器端开始建立socket描述符 */ if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1) { fprintf(stderr,"Socket error:%s\n\a",strerror(errno)); exit(1); } /* 服务器端填充 sockaddr结构 */ bzero(&server;_addr,sizeof(struct sockaddr_in)); server_addr.sin_family=AF_INET; server_addr.sin_addr.s_addr=htonl(INADDR_ANY); server_addr.sin_port=htons(portnumber); /* 捆绑sockfd描述符 */ if(bind(sockfd,(struct sockaddr *)(&server;_addr),sizeof(struct sockaddr))==-1) { fprintf(stderr,"Bind error:%s\n\a",strerror(errno)); exit(1); } /* 监听sockfd描述符 */ if(listen(sockfd,5)==-1) { fprintf(stderr,"Listen error:%s\n\a",strerror(errno)); exit(1); } while(1) { /* 服务器阻塞,直到客户程序建立连接 */ sin_size=sizeof(

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值