本例子使用异步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);
}
分享到:
相关推荐
- **异步非阻塞I/O**:使用select()、poll()或epoll()等机制,让单个线程能同时处理多个连接。 7. **测试和截图**:项目中的测试截图通常会展示服务器的启动、客户端的连接以及数据的交互过程。这有助于验证程序的...
echoserv echo 服务器,把客户端的数据不更改地返回。 编译,提供两种编译模式,windows的cygwin环境,还有linux环境。不用配置,直接make即可。 先编译core工程,在core工程下直接执行make指令 然后编译tools ...
这通常需要用到多线程或异步I/O模型,如epoll或select/poll等机制。这些技术可以提高服务器的并行处理能力,确保在高并发环境下仍能稳定运行。 此外,为了优化网络通信,EchoServer可能会采用TCP/IP协议栈中的各种...
总的来说,"Learning-Echo"项目是一个很好的学习平台,它涵盖了网络编程的核心概念和技术,有助于提升开发者对服务器实现的理解,尤其是无阻塞和异步处理在高并发场景下的应用。通过实践这个项目,不仅可以巩固C语言...
Linux网络编程是操作系统和计算机网络领域的一个重要主题,它涵盖了如何在Linux环境下设计、实现和优化网络应用程序。在这个课程中,我们将会深入探讨以下几个关键知识点: 1. **网络模型与协议**:首先,我们需要...
在Linux下进行串口编程,我们可以利用标准接口,如`poll`、`select`、`epoll`这些I/O多路复用机制,或者使用异步通知机制`fasync`。这些机制允许程序高效地监听多个文件描述符(包括串口),并及时响应GPS模块的数据...
它涉及到如何在Linux操作系统下实现网络应用程序,包括客户端和服务端的通信、数据传输、协议交互等。下面将详细介绍Linux网络编程的一些核心知识点。 1. **套接字(Socket)**:套接字是网络通信的基本接口,它允许...
例如,可以使用libevent实现一个简单的TCP服务器,通过监听一个套接字上的EV_READ事件,当有新的连接请求到来时,accept新的连接,并为每个连接创建一个新的事件,监听其EV_READ和EV_WRITE事件,以处理客户端的数据...
在"libevent demo"中,我们通常会看到一个基础的echoserver示例,它是使用libevent来实现的。Echoserver是一个简单的服务器,它接收客户端发送的数据并原样返回,常用于测试网络连接和数据传输。 **Libevent核心...
使用socket模块实现简单的服务器 ```python import socket # 创建socket对象 server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 绑定地址 server_socket.bind(('localhost', 12345)) # 开始...
同时,通过AJAX(异步JavaScript和XML)技术,可以实现无刷新的数据交换,提升用户体验。 此外,还需关注网站的安全性。防止SQL注入是必须的,可以通过预处理语句或使用参数化查询来实现。同时,确保用户密码的安全...
同样,查询客户端字符集,可以在Linux环境下运行`echo $NLS_LANG`命令。 如果在查询时发现数据呈现乱码,可能是因为客户端字符集配置不正确,或者数据库中的数据本身存在编码问题。在这种情况下,应调整客户端的NLS...
使用XMLHttpRequest对象实现异步通信,配合PHP处理后台逻辑。 10. JSON:在AJAX中,JSON(JavaScript Object Notation)常用于数据交换格式,因为它轻量级且易于解析。PHP有json_encode()和json_decode()函数进行...
- **特点**:易于学习、跨平台支持(Windows、Linux、Unix)、广泛的数据库支持(如MySQL)。 - **应用场景**:网站开发、动态网页生成、服务器端脚本执行等。 #### 二、PHP开发环境的搭建 **1. 程序编写工具的选择...
- **AJAX**:使用XMLHttpRequest对象实现异步加载数据,无需刷新整个页面即可更新部分内容。 #### 四、PHP语法 ##### 1. 最简单的PHP程序 最简单的PHP程序如下所示: ```php echo "Hello, world!"; ?> ``` 这...
- **环境要求**: Linux操作系统,推荐使用64位系统。 ##### 1.4.2 配置Redis - **配置文件**: `/etc/redis/redis.conf` 或 `/usr/local/etc/redis/redis.conf` - **关键参数**: - `bind`: 绑定监听地址。 - `port...
在Linux环境下,可以通过包管理器(如apt-get或yum)安装Redis。以Ubuntu为例,可以通过以下命令安装Redis: ```bash sudo apt-get update sudo apt-get install redis-server ``` **1.4.2 配置Redis** Redis的配置...
在Unix/Linux系统中,通常可以通过nohup命令来实现这一点。nohup命令的含义是"no hang up",它允许程序在用户退出后继续运行。例如: ```php $command = "phpscript.php"; $pid = exec("nohup $command >/dev/null ...