最好的微网站建设公司,openssl 3漏洞补丁,上海网站建设大概多少钱,俄文网站推广网络聊天室UDP实现
服务器端#xff1a;
头文件#xff1a;
#include myhead.h//定义客户信息结构体
typedef struct magtye
{char type; //消息类型char name[100]; //客户姓名char text[1024]; //客户发送聊天信息
}msg_t;//定义结构体存储…网络聊天室UDP实现
服务器端
头文件
#include myhead.h//定义客户信息结构体
typedef struct magtye
{char type; //消息类型char name[100]; //客户姓名char text[1024]; //客户发送聊天信息
}msg_t;//定义结构体存储每个客户端的ip地址和端口号
typedef struct IP_PORT
{struct sockaddr_in cin;//地址信息struct IP_PORT *next;//}*addrlist;void usr_login(int sfd,msg_t msg,addrlist *head,struct sockaddr_in cin);
void usr_chat(int sfd,msg_t msg,addrlist head,struct sockaddr_in cin);
void usr_quit(int sfd,msg_t msg,addrlist *head,struct sockaddr_in cin);
主函数
#includehead.h
int main(int argc, const char *argv[])
{//创建套接字int sfd-1;sfdsocket(AF_INET,SOCK_DGRAM, 0);if(sfd-1){perror(socket error);return -1;}//将端口号快速重用int reuse1;if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,reuse,sizeof(reuse))-1){perror(setsockopt error);return -1;}//服务器进行绑定//(1)、从终端获取端口号和地址char SER_IP[100];int SER_PORT;printf(请输入服务器ip地址和端口号);scanf(%s %d,SER_IP,SER_PORT);getchar();//吸收垃圾字符//(2)、填充服务器地址信息结构体struct sockaddr_in sin;sin.sin_familyAF_INET; //地址族sin.sin_porthtons(SER_PORT); //端口号sin.sin_addr.s_addrinet_addr(SER_IP); //IP地址 socklen_t sin_lensizeof(sin);//(3)、绑定if(bind(sfd,(struct sockaddr*)sin,sin_len)-1){perror(bind error);return -1;}//定义客户端网络信息结构体struct sockaddr_in cin;socklen_t cin_lensizeof(cin);msg_t msg;//定义客户发送消息的机构体变量//创建父子进程处理不同的操作int pidfork();if(pid-1){perror(fork error);return -1;}if(pid0)//字进程实现服务器接收消息类型{addrlist headNULL;//链表头指针;while(1){memset(msg,0,sizeof(msg));memset(cin,0,sizeof(cin));//接收客户端发来的信息并判断属于哪种消息类型recvfrom(sfd,msg,sizeof(msg),0,(struct sockaddr*)cin,cin_len);switch(msg.type){case L: //该消息类型代表新用户上线{//创建新节点保存新用户的ip地址和端口号 //向其他在线的用户发送新用户上线通知usr_login(sfd,msg,head,cin);}break;case C: //该消息类型代表一个用户发送消息给其他用户{usr_chat(sfd,msg,head,cin);}break;case Q: //该消息类型代表一个用户下线{usr_quit(sfd,msg,head,cin);}break;}}}else if(pid0)//父进程实现服务器对客户端发送消息{strcpy(msg.name,服务器消息);msg.typeC;while(1){memset(msg.text,0,sizeof(msg.text));fgets(msg.text,sizeof(msg.text),stdin);msg.text[strlen(msg.text)-1]\0;sendto(sfd,msg,sizeof(msg),0,(struct sockaddr*)sin,sin_len);if(strcmp(msg.text,服务器下线)0){sleep(1);break;}}kill(pid,SIGKILL);//服务器下线杀死子进程}wait(NULL);//关闭套接字close(sfd);return 0;
}自定义函数
#includehead.h
//用户登录操作函数
void usr_login(int sfd,msg_t msg,addrlist *head,struct sockaddr_in cin)
{//1、创建新节点addrlist s(addrlist)malloc(sizeof(addrlist));s-nextNULL;//存储新用户的ip地址和端口号printf(%s : %d\n,inet_ntoa(cin.sin_addr),ntohs(cin.sin_port));s-cincin;s-next*head;*heads;//2、遍历链表将新用户上线消息发送给其他在线用户addrlist p*head;while (p!NULL){if(p-cin.sin_port!cin.sin_port){sendto(sfd, msg, sizeof(msg),0,(struct sockaddr *)(p-cin), sizeof(p-cin));}pp-next; //后移}printf(%s:%s\n,msg.name, msg.text);}//用户聊天操作函数
void usr_chat(int sfd,msg_t msg,addrlist head,struct sockaddr_in cin)
{addrlist phead;while (p!NULL){if(p-cin.sin_port!cin.sin_port){sendto(sfd, msg, sizeof(msg),0,(struct sockaddr *)(p-cin), sizeof(p-cin));}pp-next; //后移}}
//用户退出操作函数
void usr_quit(int sfd,msg_t msg,addrlist *head,struct sockaddr_in cin)
{printf(%s:%s\n,msg.name, msg.text);addrlist p*head;addrlist delNULL;while (p!NULL){if(p-cin.sin_port!cin.sin_port) //向其他用户发送某个用户下线消息{sendto(sfd, msg, sizeof(msg),0,(struct sockaddr *)(p-cin), sizeof(p-cin));delp;pp-next;}else{sendto(sfd, msg, sizeof(msg),0,(struct sockaddr *)(p-cin), sizeof(p-cin));//向发出下线消息的用户回复消息if (delNULL) {*headp-next;} else {del-nextp-next;}free(del);delNULL;break;}}
}
客户端
#include myhead.h//定义客户信息结构体
typedef struct magtye
{char type; //消息类型char name[100]; //客户姓名char text[1024]; //客户发送聊天信息
}msg_t;int main(int argc, const char *argv[])
{//创建套接字int cfd-1;cfdsocket(AF_INET, SOCK_DGRAM, 0);if(cfd-1){perror(socket error);return -1;}//将端口号快速重用int reuse1;if(setsockopt(cfd,SOL_SOCKET,SO_REUSEADDR,reuse,sizeof(reuse))-1){perror(setsockopt error);return -1;}//(1)、从终端获取端口号和地址char SER_IP[100];int SER_PORT;printf(请输入服务器ip地址和端口号);scanf(%s %d,SER_IP,SER_PORT);getchar();//吸收垃圾字符//(2)、填充服务器地址信息结构体struct sockaddr_in sin;sin.sin_familyAF_INET; //地址族sin.sin_porthtons(SER_PORT); //端口号sin.sin_addr.s_addrinet_addr(SER_IP); //IP地址 socklen_t sin_lensizeof(sin);msg_t msg;//客户端上线发送消息printf(请输入用户名:);fgets(msg.name,sizeof(msg.name),stdin);msg.name[strlen(msg.name)-1] \0;strcpy(msg.text,已上线);msg.typeL;sendto(cfd,msg,sizeof(msg),0,(struct sockaddr*)sin,sin_len);//创建多进程进行收发消息操作int pidfork();if(pid-1){perror(fork error);return -1;}if(pid0)//父进程进行读取消息{while(1){recvfrom(cfd,msg,sizeof(msg),0,NULL,NULL);if(strcmp(msg.text,退出群聊)0) //用户自己下线{break;}printf([%s]: %s\n, msg.name, msg.text);if(strcmp(msg.text,服务器下线)0) //服务器让客户端下线{kill(pid,SIGKILL);break;}}}else if(pid0)//子进程发送消息{while(1){memset(msg.text,0,sizeof(msg.text));fgets(msg.text,sizeof(msg.text),stdin);//在终端获取聊天信息msg.text[strlen(msg.text)-1]\0;if(strcmp(msg.text, 下线)0){msg.typeQ;strcpy(msg.text, 退出群聊);}else{msg.typeC;}sendto(cfd,msg,sizeof(msg),0,(struct sockaddr*)sin,sin_len);if(strcmp(msg.text,退出群聊)0){break;}}exit(EXIT_SUCCESS);}//关闭套接字回收子进程资源wait(NULL); //阻塞回收子进程资源close(cfd);return 0;
}
思维导图