本例子使用异步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);
}
分享到:
相关推荐
Linux下基于Select模型异步串口编程总结.docx
linux-socket-select-异步聊天 linux-socket-select-异步聊天 linux-socket-select-异步聊天
linux下的使用select作为基本框架的一个简单功能的并发服务器实现
在linux下socket通讯,用select实现一个服务器对多个客户端的相互之间的通讯。用法在资料里有说明。希望对大家有帮助~~如有疑问请留言~~谢谢支持
采用I/O复用技术select实现socket通信,完成Linux下的多客户聊天室!
在linux下的socket编程服务器模型之多路复用I/O,源码经过本人编译,测试,绝对能正确运行。
Linux c - select详解 Linux c - select详解 Linux c - select详解Linux c - select详解
利用select函数在linux环境下实现的一个聊天程序,满足要求: (1)用户默认出于广播模式,一个客户在其客户端发送消息,其他客户端用户全部都可以收到; (2)程序支持下列命令 /help:显示帮助信息 /quit:用户退出...
基于linux的网络聊天室 ,在多线程 版本下修改为select版本,其中线程部分未删除,不影响功能使用
在写一个功能的时候需要根据司机查询车辆,后台数据动态追加到下拉框,因为车辆较多,所以需要用搜索,刚开始用了一种,但是跟打印功能冲突,后来找到了select2,这里有三个文件,一个js,一个css,还有一个用法说明,...
SELECT实现并发服务器,TCP服务器。
采用I/O复用技术select实现socket通信,采用多线程负责每个客户操作处理,完成Linux下的多客户聊天室! OS:Ubuntu 15.04 IDE:vim gcc make DB:Sqlite 3 Time:2015-12-09 ~ 2012-12-21 项目功能架构: 1. ...
非阻塞select 实现 socket服务器使用select 实现 非阻塞的方式 来实现 服务端
利用select函数实现I/O复用,可进行一个服务器与多个客户端的通信。-CSU某课内作业
本文实例讲述了Python通过select实现异步IO的方法。分享给大家供大家参考。具体如下: 在Python中使用select与poll比起在C中使用简单得多。select函数的参数是3个列表,包含整数文件描述符,或者带有可返回文件描述...
Echo 服务器 select模型.
linux下select和poll的用法,关于设备驱动程序中的select和poll函数的用法。
C++ 使用select模型的异步SOCKET通信 聊天室,分为服务器和客户端,简单通信模型,初熟悉select模型
Select函数实现原理分析Select函数实现原理分析Select函数实现原理分析Select函数实现原理分析
EPOLL-linux下select-poll的增强版