当前位置:网站首页>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;
}
边栏推荐
- QQ was stolen? The reason is
- With the development of industrial Internet, the landing and application of the Internet has become wider
- 嵌入式开发:5个可能不再被禁止的C特征
- [recruitment (Guangzhou)] Chenggong Yi (Guangzhou) Net core middle and Senior Development Engineer
- DNS resolution home network access public DNS practice
- Chapter 13 signal (III) - example demonstration
- 数字时代,XDR(扩展检测与响应)的无限可能
- Pytoch viewing model parameter quantity and calculation quantity
- 【观察】智能产业加速,为何AI算力要先行?
- 【Kubernetes系列】K8s设置MySQL8大小写不敏感
猜你喜欢

QQ was stolen? The reason is

Observable, reliable: the first shot of cloudops series Salon of cloud automation operation and maintenance

Loss function: Diou loss handwriting implementation

Unity animator parameter

智慧运维:基于 BIM 技术的可视化管理系统

Defi "where does the money come from"? A problem that most people don't understand

visualstudio 和sql
![[Title brushing] heater](/img/ee/70e122b1b1a406624aa7c6442fcdc1.png)
[Title brushing] heater

科普达人丨漫画图解什么是eRDMA?

SQL attendance statistics monthly report
随机推荐
重磅:国产IDE发布,由阿里研发,完全开源!
Tencent two sides: @bean and @component are used on the same class. What happens?
This editor will open source soon!
一篇文章读懂关于企业IM的所有知识点
[Title brushing] avoid flooding
Google Earth Engine(GEE)——GHSL:全球人类住区层,建成网格 1975-1990-2000-2015 (P2016) 数据集
The programming competition is coming! B station surrounding, senior members and other good gifts to you!
Loss function: Diou loss handwriting implementation
[scientific research data processing] [practice] frequency analysis chart of category variables, distribution chart of numerical variables and normality test (including lognormal)
This article explains the concepts of typed array, arraybuffer, typedarray, DataView, etc
"Persistent diseases" that cannot be solved in IM application development
Comprehensively analyze the basic features and summary of free and paid SSH tools
I want to ask how to open an account at China Merchants Securities? Is it safe to open a stock account through the link
"As a service", the inevitable choice of enterprise digital transformation
golang模板(text/template)
How to take the first step in digital transformation
深入理解.Net中的线程同步之构造模式(二)内核模式4.内核模式构造物的总结
【刷题篇】避免洪水泛滥
Unity 频繁切换分支 结果模型出现莫名其妙的错误
Introduction to the renewal of substrate source code: the pallet alliance is incorporated into the main line,