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

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

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

这是最重要的问题!当读取完数据后,需要将数据重新FD_SET进去,特别是serverFd,注意这个testFd意义非常重大,相当于参数传递中的复制行参,需要好好体会。

当read(rd)后,返回为0表示客户端的socket已经关闭,此时除了要FD_CLR,还要关闭fd!!否则fd资源没有被释放,很快就会达到select监听的上限!

[cpp]

/*

* main.cc

*

* Created on: 2009-11-30

* Author: liheyuan

* Describe: 非阻塞模式服务器(Echo服务器)

*

* Last Date: 2009-11-30

* CopyRight: 2009 @ ICT LiHeyuan

*/

#include

using namespace std;

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#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);

}

[/cpp]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值