当前位置:网站首页>Implementation of forwarding server using IO multiplexing
Implementation of forwarding server using IO multiplexing
2022-06-30 14:06:00 【Fat Xiao Deng】
// The following code is for reference only , If there are any mistakes, please comment and correct , thank you !
IO Multiplexing : Allows simultaneous control of multiple inputs and outputs .
principle : Build a file descriptor table , Using functions select, Constantly listen for file descriptors in the table to see if they are readable ( Is there any data ), If yes, the corresponding file descriptor is returned , And erase the remaining file descriptors .
Use steps :
(1) Define a set of file descriptors fd_set set;
(2) Empty the collection :FD_ZERO(&set);
(3) Add the file descriptor you want to focus on to the collection FD_SET(fd, &set);
(4) Monitor the file descriptors in the collection for actions ( Is there any data ) Use select() function ;
(5) The returned file descriptor is IO operation .
another : Deletes the specified file descriptor from the collection FD_CLR(fd, &set);
Determine whether the specified file descriptor is in the collection FD_ISSET(fd, &set);
// Server side
server.c
#include "head.h" // Header files other than those required by the kernel linked list
#include "kernel_list.h"// Header file required by kernel linked list
// Design client nodes
struct client
{
char ip[50]; // Save client ip
unsigned int port; // Save the client port
int confd; // Save client connection socket
struct list_head list; // Define the kernel linked list
};
// Chain header node
struct client *head = NULL;
// Initializing the header node
struct client *list_init(void)
{
struct client *head = calloc(1, sizeof(struct client));
if(head == NULL)
{
perror("calloc failed");
exit(0);
}
INIT_LIST_HEAD(&head->list);
}
// single shot ( To the designated person )
bool send_single(char *msg, unsigned short port)
{
struct list_head *pos = NULL;
struct client *tmp = NULL;
list_for_each(pos, &head->list)
{
tmp =list_entry(pos, struct client, list);
if(tmp->port == port)
{
write(tmp->confd, msg, strlen(msg));
return true;
}
}
return false;
}
// Mass hair
void send_broadcast(char *msg, struct client* new)
{
struct list_head *pos = NULL;
struct client *tmp = NULL;
list_for_each(pos, &head->list)
{
tmp =list_entry(pos, struct client, list);
if(tmp->port != new->port)
{
write(tmp->confd, msg, strlen(msg));
}
}
}
int main(int argc, char *argv[])
{
if(argc != 2)
{
printf("usage: %s <PORT>\n", argv[0]);
exit(0);
}
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd == -1)
{
perror("sockfd faield");
exit(0);
}
struct sockaddr_in saddr, caddr;
bzero(&saddr, sizeof(saddr));
bzero(&caddr, sizeof(caddr));
saddr.sin_family = AF_INET; //Ipv4
saddr.sin_port = htons(atoi(argv[1]));
saddr.sin_addr.s_addr = htonl(INADDR_ANY);// Automatic access to IP
if(bind(sockfd, (struct sockaddr*)&saddr, sizeof(saddr)) == -1)
{
perror("bind faield");
exit(0);
}
//printf(" Binding success \n");
if(listen(sockfd, 5) == -1)
{
perror("listen faield");
exit(0);
}
// Initialize chain header
head = list_init();
socklen_t addrlen = (socklen_t)sizeof(caddr);
int confd;
fd_set set; // Define a collection of file descriptors
struct client *pos = NULL;
int maxfd = sockfd;
struct list_head *p=NULL, *n=NULL;
char msg[100];
char *str = NULL;
// Waiting for multiple client connections
printf(" Wait for the client to connect \n");
while(1)
{
FD_ZERO(&set); // Empty the set
FD_SET(sockfd, &set); // Add the listening socket to the collection
list_for_each_entry(pos, &head->list, list)
{
FD_SET(pos->confd, &set);
// Find the maximum file descriptor
maxfd = maxfd > pos->confd ? maxfd : pos->confd;
}
// Monitor all file descriptors in the collection
select(maxfd+1, &set, NULL, NULL, NULL);
if(FD_ISSET(sockfd, &set))
{
if((confd = accept(sockfd, (struct sockaddr*)&caddr, &addrlen)) == -1)
{
perror("accept faield");
exit(0);
}
printf("[%s : %u] Successful connection \n", inet_ntoa(caddr.sin_addr), ntohs(caddr.sin_port));
struct client *new = calloc(1, sizeof(struct client));
if(new == NULL)
{
perror("calloc Create nodes failed");
exit(0);
}
strcpy(new->ip, inet_ntoa(caddr.sin_addr));
new->port = ntohs(caddr.sin_port);
new->confd = confd;
list_add_tail(&new->list, &head->list); // Insert the end of the list
}
// Find the node with action in it , Read information , If there are offline , Just delete
list_for_each_safe(p, n, &head->list)
{
pos = list_entry(p, struct client, list);
if(FD_ISSET(pos->confd, &set))
{
bzero(msg, 100);
read(pos->confd, msg, sizeof(msg));
printf("server read:%s\n", msg);
if(!strncmp(msg, "quit", 4))// Client offline
{
printf("[%s : %u] The client is offline \n", pos->ip, pos->port);
close(pos->confd); // Close socket
list_del(&pos->list); // Delete node from linked list
free(pos); // Free up the requested space
}
else if((str = strstr(msg, ":"))) // single shot
{
unsigned short port = atoi(msg);
if(!send_single(str+1, port))
{
printf(" This port was not found \n");
}
}
else // Mass hair
{
send_broadcast(msg, pos);
}
}
}
}
return 0;
}
// client
client.c
#include "head.h"
int main(int argc, char *argv[])
{
if(argc != 3)
{
printf("usage: %s <IP> <PORT>\n", argv[0]);
exit(0);
}
// Create a socket
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd == -1)
{
perror("sockfd faield");
exit(0);
}
struct sockaddr_in saddr, caddr;
bzero(&saddr, sizeof(saddr));
bzero(&caddr, sizeof(caddr));
saddr.sin_family = AF_INET; //Ipv4
saddr.sin_port = htons(atoi(argv[2]));
// saddr.sin_addr.s_addr = htonl(INADDR_ANY);// Automatic access to IP
inet_pton(AF_INET, argv[1], &saddr.sin_addr);
connect(sockfd, (struct sockaddr*)&saddr, sizeof(saddr));
printf(" Successfully connected to the server \n");
// Send message buffer
char msg[100] = {
0};
fd_set set; // Define a collection of file descriptors
while(1)
{
FD_ZERO(&set); // Empty the set
FD_SET(sockfd, &set); // Add the listening socket to the collection
FD_SET(STDIN_FILENO, &set); // Add standard input to the set
select(sockfd+1, &set, NULL, NULL, NULL);
bzero(msg, 100);
if(FD_ISSET(sockfd, &set))
{
read(sockfd, msg, 100);
printf("%s\n", msg);
}
if(FD_ISSET(STDIN_FILENO, &set))
{
fgets(msg, 100, stdin);
write(sockfd, msg, strlen(msg));
if(!strncmp(msg, "quit", 4))
break;
}
}
close(sockfd);
return 0;
}
边栏推荐
- On the simplification and acceleration of join operation
- JMeter transaction controller
- DNS 解析之家庭网络接入 Public DNS 实战
- What network security problems are exposed when a large-scale QQ number theft event occurs?
- DNS resolution home network access public DNS practice
- 表格储存中sql查询的时候,查询结果增加主键报错,查询结果超过10w行。需要对主键增加上多元索引吗?
- 知识传播不能取代专业学习!
- 【科研数据处理】[基础]类别变量频数分析图表、数值变量分布图表与正态性检验(包含对数正态)
- DeFi“钱从哪来”?一个大多数人都没搞清楚的问题
- 这个编辑器即将开源!
猜你喜欢

【观察】智能产业加速,为何AI算力要先行?

visualstudio 和sql

一文讲清楚什么是类型化数组、ArrayBuffer、TypedArray、DataView等概念

Rpm2rpm packaging steps

【刷题篇】爱吃香蕉的珂珂

可观测,才可靠:云上自动化运维CloudOps系列沙龙 第一弹

可觀測,才可靠:雲上自動化運維CloudOps系列沙龍 第一彈

MFQE 2.0: A New Approach for Multi-FrameQuality Enhancement on Compressed Video

深入理解.Net中的线程同步之构造模式(二)内核模式4.内核模式构造物的总结

步骤详解 | 助您轻松提交 Google Play 数据安全表单
随机推荐
SQL attendance statistics monthly report
golang模板(text/template)
SQL programming problem, test case failed
get请求与post提交区别的简易理解
Introduction to the renewal of substrate source code: the pallet alliance is incorporated into the main line,
【 scientific literature measurement 】 mining and visualization of keywords in foreign and Chinese Literature
How can I protect my private key?
[the path of system analyst] Chapter V software engineering (software process improvement)
智慧运维:基于 BIM 技术的可视化管理系统
On the simplification and acceleration of join operation
编程实战赛来啦!B站周边、高级会员等好礼送你啦!
More than 20 years after Hong Kong's return, Tupu digital twin Hong Kong Zhuhai Macao Bridge has shocked
LeetCode_ Stack_ Medium_ 227. basic calculator II (without brackets)
Click the TD cell of table to open the dialog pop-up window. After obtaining the value, put the value back into the TD cell
Numpy creates an empty array data = np empty(shape=[1, 64,64,3])
半导体动态杂谈
为基础性语言摇旗呐喊
Google Earth Engine(GEE)——GHSL:全球人类住区层,建成网格 1975-1990-2000-2015 (P2016) 数据集
numpy 创建空数组 data = np.empty(shape=[1, 64,64,3])
Google Earth engine (GEE) - ghsl: global human settlements layer, built grid 1975-1990-2000-2015 (p2016) data set