首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 操作系统 > UNIXLINUX >

Linux上用select()实现异步的Echo服务器

2012-07-22 
Linux下用select()实现异步的Echo服务器本例子使用异步socket(select方法)实现了ECHO服务器程序。搞了一个

Linux下用select()实现异步的Echo服务器

本例子使用异步socket(select方法)实现了ECHO服务器程序。

搞了一个晚上,终于弄好了,出现的问题主要如下:

  • 这是最重要的问题!当读取完数据后,需要将数据重新FD_SET进去,特别是serverFd,注意这个testFd意义非常重大,相当于参数传递中的复制行参,需要好好体会。
  • 当read(rd)后,返回为0表示客户端的socket已经关闭,此时除了要FD_CLR,还要关闭fd!!否则fd资源没有被释放,很快就会达到select监听的上限!
    #相关代码, [四号程序员] http://www.coder4.com/*?* main.cc?*?* ?Created on: 2009-11-30?* ? ? ?Author: liheyuan?* ? ?Describe: 非阻塞模式服务器(Echo服务器)?*?* ? Last Date: 2009-11-30?* ? CopyRight: 2009 @ ICT LiHeyuan?*/?#include <iostream>using namespace std;?#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <unistd.h>#include <sys/ioctl.h>#include <fcntl.h>#include <errno.h>#include <sys/wait.h>#include <signal.h>?#define SERVER_PORT 18000?#define SERVER_QUEUE 10#define FD_SET_SIZE 10#define MAX_BUF 16?int main() {??? ?//设置服务器Addr,在18000,任意IP监听?? ?int serverFd;?? ?serverFd = socket(AF_INET, SOCK_STREAM, 0);??? ?/* 设置 serverFd 为非阻塞方式 */?? ?int opt = SO_REUSEADDR;?? ?setsockopt(serverFd, SOL_SOCKET, opt, &opt, sizeof(opt));??? ?struct sockaddr_in serverAddr;?? ?socklen_t serverAddrLen = sizeof(sockaddr_in);?? ?serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);?? ?serverAddr.sin_port = htons(SERVER_PORT);??? ?//绑定?? ?if (bind(serverFd, (sockaddr*) &serverAddr, serverAddrLen)) {?? ? ? ?cout << "Binding on " << SERVER_PORT << " fail." << endl;?? ? ? ?return -1;?? ?}??? ?//创建等待队列?? ?listen(serverFd, SERVER_QUEUE);??? ?//设定fd_set?? ?fd_set readfds, testfds;?? ?FD_ZERO(&readfds);?? ?FD_SET(serverFd,&readfds);??? ?//非阻塞模式等待客户连接?? ?struct sockaddr_in clientAddr;?? ?int clientFd;?? ?socklen_t clientAddrLen;?? ?int len;?? ?char buf[MAX_BUF];?? ?while (1) {?? ? ? ?FD_SET(serverFd,&readfds);?? ? ? ?testfds = readfds;??? ? ? ?//选择readfds中可用的fd?? ? ? ?if (select(FD_SET_SIZE, &testfds, (fd_set *) NULL, (fd_set *) NULL,?? ? ? ? ? ? ? ?(struct timeval *) NULL) > 0) {?? ? ? ? ? ?if (FD_ISSET(serverFd,&testfds)) {?? ? ? ? ? ? ? ?//如果服务器fd可用,则为accept?? ? ? ? ? ? ? ?clientAddrLen = sizeof(sockaddr_in);?? ? ? ? ? ? ? ?clientFd = accept(serverFd, (struct sockaddr*) &clientAddr,?? ? ? ? ? ? ? ? ? ? ? ?&clientAddrLen);?? ? ? ? ? ? ? ?if (clientFd == -1) {?? ? ? ? ? ? ? ? ? ?cout << "accept() error" << endl;?? ? ? ? ? ? ? ? ? ?return -1;?? ? ? ? ? ? ? ?} else {?? ? ? ? ? ? ? ? ? ?FD_SET(clientFd,&readfds);?? ? ? ? ? ? ? ? ? ?cout << inet_ntoa(clientAddr.sin_addr) << " connect"?? ? ? ? ? ? ? ? ? ? ? ? ? ?<< " at fd" << clientFd << endl;?? ? ? ? ? ? ? ?}?? ? ? ? ? ?}?? ? ? ? ? ?//依次查询?? ? ? ? ? ?for (int fd = 0; fd < FD_SET_SIZE; fd++) {?? ? ? ? ? ? ? ?if (FD_ISSET(fd,&testfds)) {?? ? ? ? ? ? ? ? ? ?//如果是Client活动,进行Echo?? ? ? ? ? ? ? ? ? ?len = read(fd, buf, MAX_BUF);?? ? ? ? ? ? ? ? ? ?if (len > 0) {?? ? ? ? ? ? ? ? ? ? ? ?write(fd, buf, len);?? ? ? ? ? ? ? ? ? ?} else {?? ? ? ? ? ? ? ? ? ? ? ?//结束?? ? ? ? ? ? ? ? ? ? ? ?cout << "Client end at" << clientFd << endl;?? ? ? ? ? ? ? ? ? ? ? ?FD_CLR(fd,&readfds);?? ? ? ? ? ? ? ? ? ?}?? ? ? ? ? ? ? ?}?? ? ? ? ? ?}?? ? ? ?}?? ?}??? ?close(serverFd);}
    转自:http://www.coder4.com/archives/130

    ?

热点排行