当前位置:网站首页>Complete TCP forwarding server (kernel linked list + mutex)
Complete TCP forwarding server (kernel linked list + mutex)
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 !
// Server side
server.c
#include "myhead.h" // All required header files ( Except for the kernel linked list )
#include "kernel_list.h"// Kernel linked list header file
// Define a mutex
pthread_mutex_t m;
// Design client nodes
struct client
{
char ip[50]; // Save client ip
unsigned int port; // Save the client port
int connfd; // 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;
// Lock shared resources
pthread_mutex_lock(&m);
list_for_each(pos, &head->list)
{
// find pos The first address of the structure type of the linked list node ,list yes struct client Structure member of type
tmp =list_entry(pos, struct client, list);
if(tmp->port == port)
{
write(tmp->connfd, msg, strlen(msg));
pthread_mutex_unlock(&m); // Abnormal situation , Unlock first , Quit again
return true;
}
}
pthread_mutex_unlock(&m); // The normal exit , Unlock
return false;
}
// Mass hair
void send_broadcast(char *msg, struct client* new)
{
struct list_head *pos = NULL;
struct client *tmp = NULL;
// Lock shared resources
pthread_mutex_lock(&m);
list_for_each(pos, &head->list)// Traverse the linked list from scratch ( During traversal , Nodes cannot be deleted )
{
tmp =list_entry(pos, struct client, list);
if(tmp->port != new->port)
{
write(tmp->connfd, msg, strlen(msg));
}
}
pthread_mutex_unlock(&m); // Unlock shared resources
}
// Client data receiving routine
void *recvclient(void *arg)
{
struct client *new = (struct client *)arg;
char msg[100];
char *str = NULL;
// Receive client data
while(1)
{
bzero(msg, 100);
read(new->connfd, msg, sizeof(msg));
printf(" come from [%s : %u] Customer service information : %s\n", new->ip, new->port,msg);
if(strncmp(msg, "quit", 4) == 0)// Client offline
{
printf("[%s : %u] The client is offline \n", new->ip, new->port);
close(new->connfd); // Close socket
list_del(&new->list); // Delete node from linked list
free(new); // Free up the requested space
break;
}
else if((str = strstr(msg, ":"))) // single shot // strstr:( Find the specified string in a string )
{
unsigned short port = atoi(msg);
if(!send_single(str+1, port))
{
printf(" This port was not found \n");
}
}
else // Mass hair
{
send_broadcast(msg, new);
}
}
pthread_exit(NULL);
}
int main(int argc, char *argv[])
{
if(argc != 2)
{
printf("usage: %s <PORT>\n", argv[0]);
exit(0);
}
// Initialize mutex
pthread_mutex_init(&m, NULL);
int sockfd = socket(AF_INET, SOCK_STREAM, 0);//TCP
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);
}
printf(" Waiting for the connection \n");
// Initialize chain header
head = list_init(); //head After defining the structure, we define
socklen_t addrlen = (socklen_t)sizeof(caddr); //int len = sizeof(caddr);
int connfd;
// Waiting for multiple client connections
while(1)
{
if((connfd = 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(sizeof(struct client),1); // Apply for new node space
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->connfd = connfd;
// Managing shared resources —— Client linked list
pthread_mutex_lock(&m); // Lock
list_add_tail(&new->list, &head->list); // Insert the end of the list
pthread_mutex_unlock(&m); // Unlock
// Create thread , Receive client data
pthread_t tid;
pthread_create(&tid, NULL, recvclient, new);
}
return 0;
}
// The end of the service
client.c
#include "myhead.h"
// receive messages
void *Recv(void *arg)
{
int sockfd = *(int *)arg;
char msg[100];
while(1)
{
bzero(msg, 100);
read(sockfd, msg, 100);
printf("%s\n", msg);
}
pthread_exit(NULL);
}
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");
pthread_t tid;
pthread_create(&tid, NULL, Recv, &sockfd);
// Send message buffer
char msg[100] = {
0};
while(1)
{
bzero(msg, 100);
printf(" Please enter the message to send :\n");fflush(NULL);
fgets(msg, 100, stdin);
write(sockfd, msg, strlen(msg));
if(strncmp(msg, "quit", 4) == 0)
{
printf(" sign out \n");
break;
}
}
close(sockfd);
return 0;
}
** Be careful :** Connection required during compilation -lpthread
边栏推荐
- Inexplicable error occurred in unity's frequent switching branch result model
- Jetpack compose for perfect screen fit
- LeetCode_ Stack_ Medium_ 227. basic calculator II (without brackets)
- Introduction to reverse commissioning - VA and RVA conversion in PE 04/07
- MySQL如何将列合并?
- 发生QQ大规模盗号事件,暴露出什么网络安全问题?
- [observation] as the intelligent industry accelerates, why should AI computing power take the lead?
- Kaniko official documents - build images in kubernetes
- Multi terminal collaboration of Huawei accounts to create a better internet life
- 逆向调试入门-PE中的VA与RVA换算04/07
猜你喜欢
华为帐号多端协同,打造美好互联生活
Jetpack compose for perfect screen fit
Unity Animator 参数
IM即时通讯应用开发中无法解决的“顽疾”
[redis series] redis learning 16. Redis Dictionary (map) and its core coding structure
【Redis 系列】redis 学习十六,redis 字典(map) 及其核心编码结构
可观测,才可靠:云上自动化运维CloudOps系列沙龙 第一弹
深入理解.Net中的线程同步之构造模式(二)内核模式2.内核模式构造物Semaphone
Jetpack Compose 实现完美屏幕适配
[recruitment (Guangzhou)] Chenggong Yi (Guangzhou) Net core middle and Senior Development Engineer
随机推荐
visualstudio 和sql
MySQL access denied, opened as Administrator
SQL编程问题,测试用例不通过
Embedded development: five C features that may no longer be prohibited
【刷题篇】避免洪水泛滥
MFQE 2.0: A New Approach for Multi-FrameQuality Enhancement on Compressed Video
Dart 扩展特性
第四批入围企业公示——年度TOP100智能网联供应商评选
Talk about Vue's two terminal diff algorithm, analysis of the rendering principle of the mobile terminal, and whether the database primary key must be self incremented? What scenarios do not suggest s
Write, append, read, and copy of golang files: examples of using bufio packages
"As a service", the inevitable choice of enterprise digital transformation
Loss function: Diou loss handwriting implementation
【科研数据处理】[实践]类别变量频数分析图表、数值变量分布图表与正态性检验(包含对数正态)
mysql拒绝访问、管理员身份打开的
Simple understanding of the difference between get request and post submission
Directory related commands
On the simplification and acceleration of join operation
我如何才能保护我的私钥?
步骤详解 | 助您轻松提交 Google Play 数据安全表单
golang模板(text/template)