当前位置:网站首页>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;
}
边栏推荐
- 重磅:国产IDE发布,由阿里研发,完全开源!
- LeetCode_ Stack_ Medium_ 227. basic calculator II (without brackets)
- How can I protect my private key?
- 正则系列之断言Assertions
- [redis series] redis learning 16. Redis Dictionary (map) and its core coding structure
- MySQL如何将列合并?
- Observable, seulement fiable: première bombe de salon de la série cloudops d'exploitation et d'entretien automatisés dans le nuage
- "As a service", the inevitable choice of enterprise digital transformation
- 科普达人丨漫画图解什么是eRDMA?
- 60 divine vs Code plug-ins!!
猜你喜欢

Tencent two sides: @bean and @component are used on the same class. What happens?

逆向调试入门-PE中的VA与RVA换算04/07

QQ 居然被盗了?原因在这......

Optimization of unit test efficiency: why test programs? What are the benefits of testing?

Multi terminal collaboration of Huawei accounts to create a better internet life

Pytoch viewing model parameter quantity and calculation quantity

Jetpack Compose 实现完美屏幕适配

编程实战赛来啦!B站周边、高级会员等好礼送你啦!

Configuration of headquarters dual computer hot standby and branch infrastructure for firewall Foundation

mysql拒绝访问、管理员身份打开的
随机推荐
MFQE 2.0: A New Approach for Multi-FrameQuality Enhancement on Compressed Video
navicat数据库建表是没有utf8选项。
服务线上治理
深入理解.Net中的线程同步之构造模式(二)内核模式3.内核模式构造物Mutex
可观测,才可靠:云上自动化运维CloudOps系列沙龙 第一弹
【系统分析师之路】第五章 复盘软件工程(敏捷开发)
Publicity of the fourth batch of shortlisted Enterprises - annual Top100 smart Internet supplier selection
Pytoch viewing model parameter quantity and calculation quantity
What is erdma as illustrated by Coptic cartoon?
Prometheus 2.29.0 new features
I want to ask how to open an account at China Merchants Securities? Is it safe to open a stock account through the link
Waving flags and shouting for basic language
How can c write an SQL parser
【系统分析师之路】第五章 复盘软件工程(软件过程改进)
PG Basics - logical structure management (table inheritance, partition table)
Unity 频繁切换分支 结果模型出现莫名其妙的错误
How can I protect my private key?
深入理解.Net中的线程同步之构造模式(二)内核模式2.内核模式构造物Semaphone
Service online governance
[Title brushing] heater