一、select

  使用select函数可以将多个文件描述符集中到一起统一监视,监视事件如下:

  • 是否存在待读取数据。
  • 是否可传输无阻塞传输数据。
  • 是否发生异常。

  将关心上述3种事件的文件描述发分别注册到对应参数(readfds,writefds,exceptfds)中去。

  int select(int nfds, fd_set FAR * readfds, fd_set FAR * writefds, fd_set FAR * exceptfds, const struct timeval FAR * timeout);

1、linux

服务器端:

 #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h> #define BUF_SIZE 1024
void error_handling(char * messages); int main(int argc, char *argv[])
{
if(argc != )
{
printf("Usage : %s <port>\n", argv[]);
exit();
}
int serverSock, clientSock;
struct sockaddr_in serverAddr, clientAddr;
socklen_t clientAddrSize; struct timeval timeout;
fd_set reads, cpy_reads;
int fd_max, fd_num; char message[BUF_SIZE];
int strLen; serverSock =socket(PF_INET, SOCK_STREAM, );
if(serverSock == -)
error_handling("socket() error"); memset(&serverAddr, , sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
serverAddr.sin_port = htons(atoi(argv[])); if(bind(serverSock, (struct sockaddr*) &serverAddr, sizeof(serverAddr)) == -)
error_handling("bind() error");
if(listen(serverSock, ) == -)
error_handling("listen() error"); FD_ZERO(&reads);
FD_SET(serverSock, &reads);
fd_max = serverSock; puts("Server start...");
while(){
cpy_reads = reads;
timeout.tv_sec = ;
timeout.tv_usec = ; if((fd_num = select(fd_max+, &cpy_reads, , , &timeout)) == -){
error_handling("select() error");
break;
}
if(fd_num == ) continue;
for(int i = ; i <= fd_max; i++){
if(FD_ISSET(i, &cpy_reads)){
if(i == serverSock){ // connection request
clientAddrSize = sizeof(clientAddr);
clientSock = accept(serverSock, (struct sockaddr*)&clientAddr, &clientAddrSize);
FD_SET(clientSock, &reads);
if(fd_max < clientSock)
fd_max = clientSock;
printf("connected client: %d\n", clientSock);
}
else{ // read message
strLen = read(i, message, BUF_SIZE);
if(strLen == ){
FD_CLR(i, &reads);
close(i);
printf("close client: %d\n", i);
}
else{
write(i, message, strLen);
printf("echo: %d\n",i);
}
}
}
}
}
close(serverSock);
puts("Server close...");
return ;
} void error_handling(char * messages)
{
puts(messages);
exit();
}

客户端:

 #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h> #define BUF_SIZE 1024
void error_handling(char * messages); int main(int argc, char *argv[])
{
if(argc != )
{
printf("Usage : %s <IP> <port>\n", argv[]);
exit();
}
int sock;
struct sockaddr_in serv_addr;
char message[BUF_SIZE];
int strLen; sock = socket(PF_INET, SOCK_STREAM, );
if(sock == -)
error_handling("socket() error"); memset(&serv_addr, , sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr(argv[]);
serv_addr.sin_port = htons(atoi(argv[])); if(connect(sock, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) == -)
error_handling("connect() error");
else
puts("Connected...");
while(){
puts("Input message(Q to quit):");
fgets(message, BUF_SIZE, stdin);
if(!strcmp(message, "q\n") || !strcmp(message, "Q\n"))
break; strLen=strlen(message);
write(sock, message, strlen(message));
int recvLen = ;
while(recvLen < strLen){
int recvCnt = read(sock, &message[recvLen], BUF_SIZE-);
if(recvCnt == -)
error_handling("read() error");
recvLen+=recvCnt;
}
message[recvLen]=;
printf("Message from server: %s\n", message);
}
close(sock);
return ;
} void error_handling(char * messages)
{
puts(messages);
exit();
}

2、windows

服务器端:

 #include <stdio.h>
#include <stdlib.h>
#include <WinSock2.h> #define BUF_SIZE 1024
void ErrorHandling(char *message); int main(int argc, char *argv[])
{
if (argc != ) {
printf("Usage : %s <port>\n", argv[]);
exit();
} WSADATA wsa_data;
SOCKET server_sock, client_sock;
SOCKADDR_IN server_addr, client_addr;
TIMEVAL time_out;
fd_set reads, temp_reads; int addr_size;
int str_len, fd_num;
char buf[BUF_SIZE]; if (WSAStartup(MAKEWORD(, ), &wsa_data) != )
ErrorHandling("WSAStartup() error."); server_sock = socket(PF_INET, SOCK_STREAM, );
if (server_sock == INVALID_SOCKET)
ErrorHandling("socket() error."); memset(&server_addr, , sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
server_addr.sin_port = htons(atoi(argv[])); if (bind(server_sock, (SOCKADDR*)&server_addr, sizeof(server_addr)) == SOCKET_ERROR)
ErrorHandling("bind() error.");
if (listen(server_sock, ) == SOCKET_ERROR)
ErrorHandling("listen() error.");
printf("Server start...\n");
FD_ZERO(&reads);
FD_SET(server_sock, &reads);
while (true)
{
temp_reads = reads;
time_out.tv_sec = ;
time_out.tv_usec = ;
if ((fd_num = select(, &temp_reads, , , &time_out)) == SOCKET_ERROR)
break;
if (fd_num == )
continue;
for (int i = ; i < reads.fd_count; ++i)
{
if (FD_ISSET(reads.fd_array[i], &temp_reads))
{
if (reads.fd_array[i] == server_sock) // connection request
{
addr_size = sizeof(client_addr);
client_sock = accept(server_sock, (SOCKADDR*)&client_addr, &addr_size);
if (client_sock == INVALID_SOCKET)
ErrorHandling("accept() error.");
FD_SET(client_sock, &reads);
printf("connected client: %d\n", client_sock);
}
else // read message
{
str_len = recv(reads.fd_array[i], buf, BUF_SIZE - , );
if (str_len == )
{
FD_CLR(reads.fd_array[i], &reads);
closesocket(temp_reads.fd_array[i]);
printf("close client: %d\n", temp_reads.fd_array[i]);
}
else
{
send(reads.fd_array[i], buf, str_len, ); // echo
}
}
}
}
}
closesocket(server_sock);
WSACleanup();
printf("Server end...\n");
return ;
} void ErrorHandling(char *message) {
fputs(message, stderr);
fputc('\n', stderr);
}

客户端:

 #pragma warning(disable:4996)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h> #define BUF_SIZE 1024
void ErrorHandling(char *message); int main(int argc, char* argv[]) {
if (argc != ) {
printf("Usage : %s <IP> <port>\n", argv[]);
exit();
} WSADATA wsaData;
SOCKET sock;
SOCKADDR_IN serverAddr;
char message[BUF_SIZE];
int sLen, recvLen; if (WSAStartup(MAKEWORD(, ), &wsaData) != )
ErrorHandling("WSAStartup() error"); sock = socket(PF_INET, SOCK_STREAM, );
if (sock == INVALID_SOCKET)
ErrorHandling("socket() error"); memset(&serverAddr, , sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = inet_addr(argv[]);
serverAddr.sin_port = htons(atoi(argv[])); if (connect(sock, (SOCKADDR*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR)
ErrorHandling("connect() error");
else
printf("Connected.......\n");
while ()
{
fputs("Input message(Q to quit):", stdout);
fgets(message, BUF_SIZE, stdin);
if (!strcmp(message, "q\n") || !strcmp(message, "Q\n"))
break;
sLen = send(sock, message, strlen(message), );
recvLen = ;
while (recvLen < sLen) {
int cnt = recv(sock, message, BUF_SIZE - , );
if (cnt == -)
ErrorHandling("ercv() error");
recvLen += cnt;
}
message[recvLen] = ;
printf("Message from server: %s\n", message);
}
closesocket(sock);
WSACleanup();
return ;
} void ErrorHandling(char *message) {
fputs(message, stderr);
fputc('\n', stderr);
}

I/O复用(select)——回声服务器端/客户端的更多相关文章

  1. 【TCP/IP网络编程】:04基于TCP的服务器端/客户端

    摘要:结合前面所讲述的知识,本篇文章主要介绍了简单服务器端和客户端实现的框架流程及相关函数接口. 理解TCP和UDP 根据数据传输方式的不同,基于网络协议的套接字一般分为TCP套接字和UDP套接字(本 ...

  2. 【TCP/IP网络编程】:06基于UDP的服务器端/客户端

    本篇文章简单描述了UDP传输协议的工作原理及特点. 理解UDP UDP和TCP一样同属于TCP/IP协议栈的第二层,即传输层. UDP套接字的特点 UDP的工作方式类似于传统的信件邮寄过程.寄信前应先 ...

  3. 4.I/O复用以及基于I/O复用的回射客户端/服务器

    I/O复用:当一个或多个I/O条件满足时,我们就被通知到,这种能力被称为I/O复用. 1.I/O复用的相关系统调用 posix的实现提供了select.poll.epoll两类系统调用以及相关的函数来 ...

  4. MySQL服务器端&客户端常见错误

    目录(?)[+] 客户端 服务器端 客户端 1.ERROR 2013 (HY000) at line 1: Lost connection to MySQL server during query 使 ...

  5. swoolefy PHP的异步、并行、高性能网络通信引擎内置了Http/WebSocket服务器端/客户端

    近半年来努力付出,项目终于要正式结项了,团队4人经历了很多困难,加班加点,最终完成了!剩下的时间将总结一下在该项目中用到知识和遇到问题.今天就从swoole说起!项目中实现异步大文件传输的功能,在服务 ...

  6. 回声TCP服务器端/客户端

    一.TCP服务端 1.TCP服务端的默认函数调用顺序 socket()创建套接字 bind()分配套接字地址 listen()等待请求连接状态 accept()允许连接 read()/write()数 ...

  7. 使用select函数改进客户端/服务器端程序

    一.当我们使用单进程单连接且使用readline修改后的客户端程序,去连接使用readline修改后的服务器端程序,会出现一个有趣的现象,先来看输出: 先运行服务器端,再运行客户端, simba@ub ...

  8. 回声UDP服务器端/客户端

    UDP是具有数据边界的协议,传输中调用I/O函数的次数非常重要.输入函数的调用次数要和输出函数的调用次数完全一致,这样才能保证接受全部已发送的数据. TCP套接字中需注册待传输数据的目标IP和端口,而 ...

  9. I/O复用——select和poll

    概述 I/O多路复用(multiplexing)的本质是通过一种机制(系统内核缓冲I/O数据),让单个进程可以监视多个文件描述符,一旦某个描述符就绪(一般是读就绪或写就绪),能够通知程序进行相应的读写 ...

随机推荐

  1. idea使用教程(1)

    引言:本教程主要讲解一下常用的配置安装方法,不包含软件安装,按照以下教程配置后,可以直接用于生产环境. 参考网址:参考了尚硅谷关于idea的使用教学视屏 idea注册码地址:http://idea.l ...

  2. Django 日志

    Django使用Python内置的logging模块实现它自己的日志系统. 如果你没有使用过logging模块,请参考Python教程中的相关章节. 直达链接<logging模块详解>. ...

  3. [原][unreal][UE][spark]分析unreal engine 虚幻引擎的粒子编辑器:Cascade

    参考:https://www.raywenderlich.com/270-unreal-engine-4-particle-systems-tutorial (使用了一个飞机射击游戏的粒子来展示,全英 ...

  4. wow 滚动动画

    1.demo <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset=" ...

  5. java与js交互,相互调用传参

    随着前端技术的发展与H5的广泛使用,移动端采用native+h5的方式越来越多了,对于Android来说就涉及到java与js的交互,相互调用传参等.下面就来看一下java与js交互的简单demo. ...

  6. array_map的使用

    其结果为:

  7. 确认OHS版本的方法

    还是 opatch lsinventory 好用 C:\Oracle\Middleware\ohs\OPatch>opatch lsinventory Oracle Interim Patch ...

  8. MyBatis-session-SqlSession

    The SqlSession instance is the most powerful in MyBatis. It is where you'll find all of the methods ...

  9. Server SQL Modes

    The MySQL server can operate in different SQL modes, and can apply these modes differently for diffe ...

  10. css图片的全屏显示代码-css3

    <!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8" ...