您的位置:首页 > 科技 > IT业 > UDP网络聊天室

UDP网络聊天室

2024/9/22 9:41:57 来源:https://blog.csdn.net/slander_1120/article/details/139177517  浏览:    关键词:UDP网络聊天室

前言

基于UDP的网络聊天室

一、项目需求

  1. 如果有用户登录,其他用户可以收到这个人的登录信息
  2. 如果有人发送信息,其他用户可以收到这个人的群聊信息
  3. 如果有人下线,其他用户可以收到这个人的下线信息
  4. 服务器可以发送系统信息

二、步骤

1.创建UDP服务器

1.1 头文件

 #include <stdio.h>#include <string.h>#include <stdlib.h>#include <math.h>#include <sys/types.h>#include <unistd.h>#include <sys/stat.h>#include <fcntl.h>#include <pthread.h>#include <semaphore.h>#include <wait.h>#include <signal.h>#include <sys/socket.h>#include <arpa/inet.h>#include <sys/ipc.h>#include <sys/sem.h>#include <semaphore.h>#include <sys/msg.h>#include <sys/shm.h>#include <sys/un.h>#include <netinet/in.h>#include <arpa/inet.h>#include <errno.h>#include <sys/select.h>#include <poll.h>#include <sqlite3.h>

1.2 定义宏 

#define BUFSIZE 1024//定义缓冲区大小
#define login_msg_len 20//定义登录消息长度

1.3 定义链表节点  数据传递消息类型

/*定义链表节点*/
typedef struct Node{char name[login_msg_len];struct sockaddr_in addr;struct Node *next;
}Node;/*定义消息类型*/
typedef struct Msgtype{char type;char username[login_msg_len];char content[BUFSIZE];
}Msgtype;

1.4 声明函数

Node *create_node(in_port_t SER_PORT,const char * SER_IP_STR);/*创建单向链表*/
Node *add_node(char *name,struct sockaddr_in addr);/*向链表中添加节点*/
int print_msg(Msgtype *msg);/*打印消息类型*/
void broadcast(int sfd,Node *head,Msgtype *msg);/*广播消息*/
int is_exist(Node *head,Msgtype *msg);/*查找用户名是否存在*/
int is_empty(Node *head);/*链表判空*/
void insert_node(Node *head,char *name,struct sockaddr_in addr);/*头插法插入节点*/
void delete_node(Node *head,char *name);/*按用户名删除节点*/
void broadcast_system(int sfd,Node *head,char *input_buf);/*向所有客户端发送系统消息*/

1.5  创建单向链表

Node *create_node(in_port_t SER_PORT,const char * SER_IP_STR){Node *node=(Node*)malloc(sizeof(Node));if(node==NULL){perror("malloc");exit(1);}char *msg="system";for(int i=0;i<sizeof(msg);i++){node->name[i]=msg[i];}node->addr.sin_family=AF_INET;node->addr.sin_port=htons(SER_PORT);node->addr.sin_addr.s_addr=inet_addr(SER_IP_STR);node->next=NULL;return node;
}

1.6  向链表中加入节点

Node *add_node(char *name,struct sockaddr_in addr){Node *new_node=(Node*)malloc(sizeof(Node));if(new_node==NULL){perror("malloc");exit(1);}strcpy(new_node->name,name);new_node->addr=addr;new_node->next=NULL;return new_node;
}

1.7 对链表判空

int is_empty(Node *head){if(head==NULL){return 1;}return head->next==NULL?1:0;
}

1.8 插入节点

oid insert_node(Node *head,char *name,struct sockaddr_in addr){if(head==NULL){perror("head is null");exit(1);}   Node *new_node=add_node(name,addr);new_node->next=head->next;head->next=new_node;printf("%s进入聊天室\n",name);
}

1.9 判断数据模式

int print_msg(Msgtype *msg){switch(msg->type){case 'L':return 1;case 'C':return 2;case 'Q':return 3;default:return 0;}
}

2.0 查找用户是否存在

int is_exist(Node *head,Msgtype *msg){if(head==NULL){perror("head is null");exit(1);}if(is_empty(head)){return 0;}Node *p=head->next;while(p!=NULL){if(strcmp(p->name,msg->username)==0){return 1;}p=p->next;}return 0;
}

2.1 广播消息 

void broadcast(int sfd,Node *head,Msgtype *msg){if(head==NULL){perror("head is null");exit(1);}if(is_empty(head)){printf("聊天室为空\n");return;}Node *p=head->next;while(p!=NULL){/*发送消息*/if(strcmp(p->name,msg->username)!=0){sendto(sfd,msg,sizeof(Msgtype),0,(struct sockaddr*)&p->addr,sizeof(p->addr));}p=p->next;}
}

2.2 按用户名删除用户节点

void delete_node(Node *head,char *name){if(head==NULL){perror("head is null");exit(1);}if(is_empty(head)){printf("聊天室为空\n");return;}printf("%s退出聊天室\n",name);Node *p=head->next;Node *pre=head;while(p!=NULL){if(strcmp(p->name,name)==0){pre->next=p->next;free(p);return;}pre=p;p=p->next;}

2.3 广播系统信息

void broadcast_system(int sfd,Node *head,char *content){if(head==NULL){perror("head is null");exit(1);}if(is_empty(head)){printf("聊天室为空\n");return;}Msgtype msg;msg.type='C';strcpy(msg.username,"system");strcpy(msg.content,content);Node *p=head->next;while(p!=NULL){/*发送消息*/sendto(sfd,&msg,sizeof(Msgtype),0,(struct sockaddr*)&p->addr,sizeof(p->addr));p=p->next;}printf("system发送消息:%s\n",content);
}

2.4 创建套接字,绑定IP,端口信息

/*获取IP地址和端口*/if(3>argc){printf("输入格式不对,请按照以下格式输入:./server ip port\n");exit(1);}const char *SER_IP_STR=argv[1];in_port_t SER_PORT=atoi(argv[2]);/*创建UDP套接字*/int sfd=-1;if((sfd=socket(AF_INET,SOCK_DGRAM,0))<0){perror("socket");exit(1);} /*设置UDP服务器的地址*/struct sockaddr_in addr;memset(&addr,0,sizeof(addr));addr.sin_family=AF_INET;addr.sin_port=htons(SER_PORT);if(inet_aton(SER_IP_STR,&addr.sin_addr)==0){perror("inet_aton");exit(1);}/*绑定端口*/if(bind(sfd,(struct sockaddr*)&addr,sizeof(addr))<0){perror("bind");exit(1);}printf("bind success\n");

2.5 创建链表

/*创建链表*/Node *head=create_node(SER_PORT,SER_IP_STR);

2.6 使用poll实现并发执行

/*监控服务器响应*/struct pollfd pfd[2];pfd[0].fd = sfd;        // 监控套接字pfd[0].events = POLLIN; // 监控读事件pfd[1].fd = 0;          // 监控标准输入pfd[1].events = POLLIN; // 监控读事件
/*等待IO事件*/int ret=poll(pfd,2,-1);if(ret<0){perror("poll");exit(1);}else if (ret==0){printf("poll timeout\n");continue;}
if(pfd[0].revents==POLLIN){
}
if(pfd[1].revents==POLLIN){
}

2.7  创建接收客户端网络信息,数据信息的结构体

/*创建接收客户端网络信息的结构体*/struct sockaddr_in client_addr;socklen_t client_addr_len=sizeof(client_addr);/*创建客户端数据信息的结构体*/Msgtype client_msg;memset(&client_msg,0,sizeof(client_msg));

 2.8 接收数据处理

int recv_len=recvfrom(sfd,&client_msg,sizeof(client_msg),0,(struct sockaddr*)&client_addr,&client_addr_len);if(recv_len<0){perror("recvfrom");exit(1);}/*判断消息类型*//*登录类型*/if(print_msg(&client_msg)==1){/*判断用户是否存在*/if(is_exist(head,&client_msg)){/*向客户端发送用户名已存在消息*/client_msg.type='E';sendto(sfd,&client_msg,sizeof(client_msg),0,(struct sockaddr*)&client_addr,sizeof(client_addr));continue;}else{/*向链表中插入节点*/insert_node(head,client_msg.username,client_addr);/*向客户端发送登录成功消息*/client_msg.type='L';strcpy(client_msg.content,"进入聊天室");/*向所有客户端发送登录消息*/broadcast(sfd,head,&client_msg);}}else if (print_msg(&client_msg)==2){/*客户端数据传输类型*//*向所有客户端发送消息*/printf("%s发送消息\n",client_msg.username);broadcast(sfd,head,&client_msg);}else if (print_msg(&client_msg)==3){/*客户端退出登录类型*//*删除节点*/delete_node(head,client_msg.username);/*向客户端发送退出登录消息*/client_msg.type='Q';strcpy(client_msg.content,"退出聊天室");broadcast(sfd,head,&client_msg);}else{/*客户端消息类型错误*/char *msg="消息类型错误";for(int i=0;i<sizeof(msg);i++){client_msg.content[i]=msg[i];}sendto(sfd,&client_msg,sizeof(client_msg),0,(struct sockaddr*)&client_addr,sizeof(client_msg));continue; }

 2.9 发送数据处理

/*服务器终端输入*/char input_buf[BUFSIZE];fgets(input_buf,BUFSIZE,stdin);input_buf[strlen(input_buf)-1]='\0';/*判断客户端是否登录*/if(is_empty(head)){printf("聊天室为空,请等待其他用户登录\n");continue;}/*向所有客户端发送消息*/broadcast_system(sfd,head,input_buf);

 2.创建UDP客户端

1.1 定义宏

#define BUFSIZE 1024//定义缓冲区大小
#define login_msg_len 20//定义登录信息长度

1.2 定义数据信息结构体

typedef struct Msgtype{char type;char username[login_msg_len];char content[BUFSIZE];
}Msgtype;

1.3 创建套接字,绑定服务器

 /*获取IP地址和端口*/if(3>argc){printf("输入格式不对,请按照以下格式输入:./server ip port\n");}const char *SER_IP_STR=argv[1];int SER_PORT=atoi(argv[2]);/*创建UDP套接字*/int sfd=-1;if((sfd=socket(AF_INET,SOCK_DGRAM,0))<0){perror("socket");exit(1);}/*设置服务器地址*/struct sockaddr_in server_addr;memset(&server_addr,0,sizeof(server_addr));server_addr.sin_family=AF_INET;server_addr.sin_port=htons(SER_PORT);if(inet_aton(SER_IP_STR,&server_addr.sin_addr)==0){perror("inet_aton");exit(1);}socklen_t addr_len=sizeof(server_addr);

 1.4 创建客户端数据手收发结构体,用户登录信息结构体

/*创建客户端数据收发结构体*/Msgtype recv_msg;memset(&recv_msg,0,sizeof(recv_msg));Msgtype send_msg;memset(&send_msg,0,sizeof(send_msg));/*创建用户登录信息*/Msgtype login_msg;

1.5  用户登录

 /*登录服务器*/memset(&login_msg,0,sizeof(login_msg));login_msg.type='L';printf("请输入用户名:");fgets(login_msg.username, login_msg_len, stdin);login_msg.username[strcspn(login_msg.username, "\n")] = '\0'; // 去掉换行符/*发送登录信息*/if (sendto(sfd, &login_msg, sizeof(login_msg), 0, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0){perror("sendto");exit(1);}

1.6 使用poll实现并发 

/*监控服务器响应*/struct pollfd pfd[2];pfd[0].fd = sfd;        // 监控套接字pfd[0].events = POLLIN; // 监控读事件pfd[1].fd = 0;          // 监控标准输入pfd[1].events = POLLIN; // 监控读事件;
/*等待IO事件*/int ret=poll(pfd,2,-1);if(ret<0){perror("poll");exit(1);}else if (ret==0)   {printf("poll timeout\n");continue;}
if(pfd[0].revents==POLLIN){
}
if(pfd[1].revents==POLLIN){
}

 1.7 根据条件进行并发执行终端输入,数据接收

if(pfd[0].revents==POLLIN){/*接收服务器消息*/int len=recvfrom(sfd, &recv_msg, sizeof(recv_msg), 0, (struct sockaddr *)&server_addr, &addr_len);if(len<0){perror("recvfrom");exit(1);}if(recv_msg.type=='L'){printf("-----------%s加入聊天室----------\n",recv_msg.username);}else if(recv_msg.type=='C'){printf("%s:%s\n",recv_msg.username,recv_msg.content);}else if (recv_msg.type=='Q') {printf("------------%s%s---------------\n",recv_msg.username,recv_msg.content);}else{printf("%s用户名已存在或服务器故障,请重新登录\n",login_msg.username);break;}}if(pfd[1].revents==POLLIN){/*接收用户输入*/char input[BUFSIZE];fgets(input,BUFSIZE, stdin);input[strcspn(input, "\n")] = '\0'; // 去掉换行符if(strcmp(input,"quit")==0){send_msg.type='Q';sendto(sfd, &send_msg, sizeof(send_msg), 0, (struct sockaddr *)&server_addr, sizeof(server_addr));break;//退出循环}else{/*发送消息*/memset(&send_msg,0,sizeof(send_msg));send_msg.type='C';strncpy(send_msg.username,login_msg.username,login_msg_len);strncpy(send_msg.content,input,BUFSIZE);sendto(sfd, &send_msg, sizeof(send_msg), 0, (struct sockaddr *)&server_addr, sizeof(server_addr));}}

 3.服务器最终程序

#include <myhead.h>
#define BUFSIZE 1024//定义缓冲区大小
#define login_msg_len 20//定义登录消息长度/*定义链表节点*/
typedef struct Node{char name[login_msg_len];struct sockaddr_in addr;struct Node *next;
}Node;/*定义消息类型*/
typedef struct Msgtype{char type;char username[login_msg_len];char content[BUFSIZE];
}Msgtype;/*声明函数*/
Node *create_node(in_port_t SER_PORT,const char * SER_IP_STR);/*创建单向链表*/
Node *add_node(char *name,struct sockaddr_in addr);/*向链表中添加节点*/
int print_msg(Msgtype *msg);/*打印消息类型*/
void broadcast(int sfd,Node *head,Msgtype *msg);/*广播消息*/
int is_exist(Node *head,Msgtype *msg);/*查找用户名是否存在*/
int is_empty(Node *head);/*链表判空*/
void insert_node(Node *head,char *name,struct sockaddr_in addr);/*头插法插入节点*/
void delete_node(Node *head,char *name);/*按用户名删除节点*/
void broadcast_system(int sfd,Node *head,char *input_buf);/*向所有客户端发送系统消息*/int main(int argc, char const *argv[])
{   /*获取IP地址和端口*/if(3>argc){printf("输入格式不对,请按照以下格式输入:./server ip port\n");exit(1);}const char *SER_IP_STR=argv[1];in_port_t SER_PORT=atoi(argv[2]);/*创建UDP套接字*/int sfd=-1;if((sfd=socket(AF_INET,SOCK_DGRAM,0))<0){perror("socket");exit(1);} /*设置UDP服务器的地址*/struct sockaddr_in addr;memset(&addr,0,sizeof(addr));addr.sin_family=AF_INET;addr.sin_port=htons(SER_PORT);if(inet_aton(SER_IP_STR,&addr.sin_addr)==0){perror("inet_aton");exit(1);}/*绑定端口*/if(bind(sfd,(struct sockaddr*)&addr,sizeof(addr))<0){perror("bind");exit(1);}printf("bind success\n");/*创建链表*/Node *head=create_node(SER_PORT,SER_IP_STR);/*监控服务器响应*/struct pollfd pfd[2];pfd[0].fd = sfd;        // 监控套接字pfd[0].events = POLLIN; // 监控读事件pfd[1].fd = 0;          // 监控标准输入pfd[1].events = POLLIN; // 监控读事件/*创建接收客户端网络信息的结构体*/struct sockaddr_in client_addr;socklen_t client_addr_len=sizeof(client_addr);/*创建客户端数据信息的结构体*/Msgtype client_msg;memset(&client_msg,0,sizeof(client_msg));/*循环接收客户端信息*/while(1){/*等待IO事件*/int ret=poll(pfd,2,-1);if(ret<0){perror("poll");exit(1);}else if (ret==0){printf("poll timeout\n");continue;}if(pfd[0].revents==POLLIN){/*接收客户端登录信息*/int recv_len=recvfrom(sfd,&client_msg,sizeof(client_msg),0,(struct sockaddr*)&client_addr,&client_addr_len);if(recv_len<0){perror("recvfrom");exit(1);}/*判断消息类型*//*登录类型*/if(print_msg(&client_msg)==1){/*判断用户是否存在*/if(is_exist(head,&client_msg)){/*向客户端发送用户名已存在消息*/client_msg.type='E';sendto(sfd,&client_msg,sizeof(client_msg),0,(struct sockaddr*)&client_addr,sizeof(client_addr));continue;}else{/*向链表中插入节点*/insert_node(head,client_msg.username,client_addr);/*向客户端发送登录成功消息*/client_msg.type='L';strcpy(client_msg.content,"进入聊天室");/*向所有客户端发送登录消息*/broadcast(sfd,head,&client_msg);}}else if (print_msg(&client_msg)==2){/*客户端数据传输类型*//*向所有客户端发送消息*/printf("%s发送消息\n",client_msg.username);broadcast(sfd,head,&client_msg);}else if (print_msg(&client_msg)==3){/*客户端退出登录类型*//*删除节点*/delete_node(head,client_msg.username);/*向客户端发送退出登录消息*/client_msg.type='Q';strcpy(client_msg.content,"退出聊天室");broadcast(sfd,head,&client_msg);}else{/*客户端消息类型错误*/char *msg="消息类型错误";for(int i=0;i<sizeof(msg);i++){client_msg.content[i]=msg[i];}sendto(sfd,&client_msg,sizeof(client_msg),0,(struct sockaddr*)&client_addr,sizeof(client_msg));continue; }}if(pfd[1].revents==POLLIN){/*服务器终端输入*/char input_buf[BUFSIZE];fgets(input_buf,BUFSIZE,stdin);input_buf[strlen(input_buf)-1]='\0';/*判断客户端是否登录*/if(is_empty(head)){printf("聊天室为空,请等待其他用户登录\n");continue;}/*向所有客户端发送消息*/broadcast_system(sfd,head,input_buf);}}/*关闭套接字*/close(sfd);return 0;
}
/*创建单向链表*/
Node *create_node(in_port_t SER_PORT,const char * SER_IP_STR){Node *node=(Node*)malloc(sizeof(Node));if(node==NULL){perror("malloc");exit(1);}char *msg="system";for(int i=0;i<sizeof(msg);i++){node->name[i]=msg[i];}node->addr.sin_family=AF_INET;node->addr.sin_port=htons(SER_PORT);node->addr.sin_addr.s_addr=inet_addr(SER_IP_STR);node->next=NULL;return node;
}
/*向链表中添加节点*/
Node *add_node(char *name,struct sockaddr_in addr){Node *new_node=(Node*)malloc(sizeof(Node));if(new_node==NULL){perror("malloc");exit(1);}strcpy(new_node->name,name);new_node->addr=addr;new_node->next=NULL;return new_node;
}
/*链表判空*/
int is_empty(Node *head){if(head==NULL){return 1;}return head->next==NULL?1:0;
}
/*头插法插入节点*/
void insert_node(Node *head,char *name,struct sockaddr_in addr){if(head==NULL){perror("head is null");exit(1);}   Node *new_node=add_node(name,addr);new_node->next=head->next;head->next=new_node;printf("%s进入聊天室\n",name);
}
/*判断数据模式*/
int print_msg(Msgtype *msg){switch(msg->type){case 'L':return 1;case 'C':return 2;case 'Q':return 3;default:return 0;}
}
/*查找用户名是否存在*/
int is_exist(Node *head,Msgtype *msg){if(head==NULL){perror("head is null");exit(1);}if(is_empty(head)){return 0;}Node *p=head->next;while(p!=NULL){if(strcmp(p->name,msg->username)==0){return 1;}p=p->next;}return 0;
}
/*广播消息*/
void broadcast(int sfd,Node *head,Msgtype *msg){if(head==NULL){perror("head is null");exit(1);}if(is_empty(head)){printf("聊天室为空\n");return;}Node *p=head->next;while(p!=NULL){/*发送消息*/if(strcmp(p->name,msg->username)!=0){sendto(sfd,msg,sizeof(Msgtype),0,(struct sockaddr*)&p->addr,sizeof(p->addr));}p=p->next;}
}
/*按用户名删除节点*/
void delete_node(Node *head,char *name){if(head==NULL){perror("head is null");exit(1);}if(is_empty(head)){printf("聊天室为空\n");return;}printf("%s退出聊天室\n",name);Node *p=head->next;Node *pre=head;while(p!=NULL){if(strcmp(p->name,name)==0){pre->next=p->next;free(p);return;}pre=p;p=p->next;}}
/*广播system消息*/
void broadcast_system(int sfd,Node *head,char *content){if(head==NULL){perror("head is null");exit(1);}if(is_empty(head)){printf("聊天室为空\n");return;}Msgtype msg;msg.type='C';strcpy(msg.username,"system");strcpy(msg.content,content);Node *p=head->next;while(p!=NULL){/*发送消息*/sendto(sfd,&msg,sizeof(Msgtype),0,(struct sockaddr*)&p->addr,sizeof(p->addr));p=p->next;}printf("system发送消息:%s\n",content);
}

 4.客户端最终程序

#include <myhead.h>
#define BUFSIZE 1024//定义缓冲区大小
#define login_msg_len 20//定义登录信息长度/*定义消息类型*/
typedef struct Msgtype{char type;char username[login_msg_len];char content[BUFSIZE];
}Msgtype;int main(int argc, char const *argv[])
{   /*获取IP地址和端口*/if(3>argc){printf("输入格式不对,请按照以下格式输入:./server ip port\n");}const char *SER_IP_STR=argv[1];int SER_PORT=atoi(argv[2]);/*创建UDP套接字*/int sfd=-1;if((sfd=socket(AF_INET,SOCK_DGRAM,0))<0){perror("socket");exit(1);}/*设置服务器地址*/struct sockaddr_in server_addr;memset(&server_addr,0,sizeof(server_addr));server_addr.sin_family=AF_INET;server_addr.sin_port=htons(SER_PORT);if(inet_aton(SER_IP_STR,&server_addr.sin_addr)==0){perror("inet_aton");exit(1);}socklen_t addr_len=sizeof(server_addr);/*创建客户端数据收发结构体*/Msgtype recv_msg;memset(&recv_msg,0,sizeof(recv_msg));Msgtype send_msg;memset(&send_msg,0,sizeof(send_msg));/*创建用户登录信息*/Msgtype login_msg;while (1){/*登录服务器*/memset(&login_msg,0,sizeof(login_msg));login_msg.type='L';printf("请输入用户名:");fgets(login_msg.username, login_msg_len, stdin);login_msg.username[strcspn(login_msg.username, "\n")] = '\0'; // 去掉换行符/*发送登录信息*/if (sendto(sfd, &login_msg, sizeof(login_msg), 0, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0){perror("sendto");exit(1);}/*监控服务器响应*/struct pollfd pfd[2];pfd[0].fd = sfd;        // 监控套接字pfd[0].events = POLLIN; // 监控读事件pfd[1].fd = 0;          // 监控标准输入pfd[1].events = POLLIN; // 监控读事件;while(1){/*等待IO事件*/int ret=poll(pfd,2,-1);if(ret<0){perror("poll");exit(1);}else if (ret==0)   {printf("poll timeout\n");continue;}if(pfd[0].revents==POLLIN){/*接收服务器消息*/int len=recvfrom(sfd, &recv_msg, sizeof(recv_msg), 0, (struct sockaddr *)&server_addr, &addr_len);if(len<0){perror("recvfrom");exit(1);}if(recv_msg.type=='L'){printf("-----------%s加入聊天室----------\n",recv_msg.username);}else if(recv_msg.type=='C'){printf("%s:%s\n",recv_msg.username,recv_msg.content);}else if (recv_msg.type=='Q') {printf("------------%s%s---------------\n",recv_msg.username,recv_msg.content);}else{printf("%s用户名已存在或服务器故障,请重新登录\n",login_msg.username);break;}}if(pfd[1].revents==POLLIN){/*接收用户输入*/char input[BUFSIZE];fgets(input,BUFSIZE, stdin);input[strcspn(input, "\n")] = '\0'; // 去掉换行符if(strcmp(input,"quit")==0){send_msg.type='Q';sendto(sfd, &send_msg, sizeof(send_msg), 0, (struct sockaddr *)&server_addr, sizeof(server_addr));break;//退出循环}else{/*发送消息*/memset(&send_msg,0,sizeof(send_msg));send_msg.type='C';strncpy(send_msg.username,login_msg.username,login_msg_len);strncpy(send_msg.content,input,BUFSIZE);sendto(sfd, &send_msg, sizeof(send_msg), 0, (struct sockaddr *)&server_addr, sizeof(server_addr));}}}}close(sfd);return 0;
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com