1.服务器

1.服务器采用了线程进行编写,这样可以共享链表,比较简单。

2.实现思路:由客户端发送消息(内容包含:客户端自定义的名字、客户端发送消息的类别、客户端发送的消息内容),服务器接收到消息后根据消息的类别做出一下反应。

1.消息类别:登录。服务器将接收到的消息显示在服务器上,并且遍历链表发送给除改客户端的其他客户端。然后创建一个节点保存客户端的IP和端口号。

2.消息类别:发送消息。服务器将接收到的消息显示在服务器上,并且遍历链表发送给除改客户端的其他客户端。

3.消息类别:下线。服务器将接收到的消息显示在服务器上,并且遍历链表发送给除改客户端的其他客户端。当遍历到改客户端时,删除改节点。

3.当服务器要发送消息时,在子线程里面接收来自终端上的消息,遍历链表发送给所有客户端。

/*===============================================*   文件名称:server.c*   创 建 者:懒  *   创建日期:2022年10月09日*   描    述:================================================*/
#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <pthread.h>typedef struct linklist{//创建存储客户端ip、端口号的链表struct sockaddr_in addr;struct linklist* next;
}l_node, *l_pnode;typedef struct sockt_data{//创建收发的信息结构体char name[64];//名字char type[8];//消息类别char text[128];//信息内容
}data_t;typedef struct Sock{//创建存储服务器发送数据的信息结构体struct sockaddr_in caddr; data_t cdata;//发送消息结构体int sockfd;//套接字
}sock_t;l_pnode create();//创建链表节点
void login(int sockfd,data_t data,struct sockaddr_in saddr);//登录
void line(int sockfd,data_t data,struct sockaddr_in saddr);//发送和下线
void *func(void *arg);//子线程l_pnode S;//开辟一个全局变量的链表int main(int argc, char *argv[])
{ /**************** 1、创建套接字 -- socket *********************/int sockfd = socket(AF_INET, SOCK_DGRAM, 0);/****************2、绑定IP地址和端口号 -- bind ****************/struct sockaddr_in saddr, caddr;caddr.sin_family = AF_INET;caddr.sin_port = htons(8888);//将主机字节序转换为网络字节序再赋值caddr.sin_addr.s_addr = htons(INADDR_ANY);int s_len = sizeof(saddr);bind(sockfd, (struct sockaddr*)&caddr, s_len);/**************** 3、发送接送数据 *****************************/data_t sdata={0,0,0};//定义接送数据结构体int d_len=sizeof(sdata);int c_len = sizeof(caddr);//计算服务器地址结构的大小memset(&saddr, 0,c_len);//清空接收地址结构S = (l_pnode)malloc(sizeof(l_node));//初始化链表S->next=NULL;sock_t csock;//创建子线程所需结构体csock.sockfd=sockfd;//传递套接字pthread_t thread;pthread_create(&thread,NULL,func,&csock); //创建子线程while(1){    memset(&sdata, 0, d_len);//清空接送到的数据recvfrom(sockfd, &sdata, d_len, 0, (struct sockaddr*)&saddr, &c_len);//接送来自客户端的消息printf("%s:%s\n",sdata.name,sdata.text);//在服务器中显示接送到的消息if(strcmp(sdata.type,"login")==0)//判断接受消息内型login(sockfd,sdata,saddr);//上线操作else    line(sockfd,sdata,saddr);//聊天、下线操作}/**************** 4、关闭套接字 *******************************/close(sockfd);return 0;
} /**************** 子线程 **************************************/
void *func(void *arg)   //线程处理函数
{sock_t csock=*(sock_t *)arg;//获取主函数中传递过来的内容strcpy(csock.cdata.type,"login");//设置要发送的结构图strcpy(csock.cdata.name,"服务器");while(1){memset(&csock.cdata.text, 0,128);//清空输入进来的内容fgets(csock.cdata.text,64,stdin);//获取输入进来的内容csock.cdata.text[strlen(csock.cdata.text)-1] = '\0';//删除获取进来的回车'\n'line(csock.sockfd,csock.cdata,csock.caddr);//向所有在线的客户端发送入进来的内容}
}/**************** 上线 ***************************************/
void login(int sockfd,data_t data,struct sockaddr_in saddr)//登录
{int d_len = sizeof(data);int s_len = sizeof(saddr);l_pnode new = create();//创建新节点new->addr = saddr;//传递接送到的客户端IP、端口号new->next = NULL;l_pnode N = create();N=S;while(N->next)//尾插并发送给其他客户端{N = N->next;sendto(sockfd, &data, d_len, 0, (struct sockaddr*)&N->addr, s_len);//发送给除该客户信息的其他客户}N->next = new;
}/**************** 聊天、下线 *******************************/
void line(int sockfd,data_t data,struct sockaddr_in saddr)//聊天、下线
{int d_len = sizeof(data);int s_len = sizeof(saddr);l_pnode N = create();N=S;while(N->next){if((N->next->addr.sin_addr.s_addr==saddr.sin_addr.s_addr)&& (N->next->addr.sin_port==saddr.sin_port))//判断是否存在该客户端数据{if(strcmp(data.type,"line")==0)//下线,删除用户信息{l_pnode Q = N->next;N->next = Q->next;//连线free(Q);//释放空间Q = NULL;}if(strcmp(data.type,"send_t")==0)//聊天,跳过用户N = N->next;}if(N->next != NULL)//判断是否到尾节点{N = N->next;sendto(sockfd, &data, d_len, 0, (struct sockaddr*)&N->addr, s_len);//发送给除该客户信息的其他客户}elsebreak;}
}/**************** 创建链表新节点 ******************************/
l_pnode create()
{l_pnode S = (l_pnode)malloc(sizeof(l_node));S->next = NULL;return S;
}

2.客户端

1.客户端采用了进程进行编写,由子进程接收来自终端的消息发送出去,由父进程来接收消息。当运行程序时。

1.要求需要输入用户名,输入用户名后会向服务器发送(用户名、消息类别:登录、内容:上线了)。

2.客户端发送消息(用户名、消息类别:聊天、内容:消息内容)。

2.客户端下线,需要用户输入“line!!!”(用户名、消息类别:下线、内容:下线了)。接受程序。

2.当接受来自服务器的消息,将消息里的名字和内容打印出来

/*===============================================*   文件名称:client.c*   创 建 者:懒  *   创建日期:2022年10月09日*   描    述:================================================*/
#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>typedef struct sockt_data{//自定义结构体用于存放发送、接送到的信息char name[64];char type[8];char text[128];
}data_t;void mysignal(int arg)//回收子进程
{wait(NULL);exit(0);
}void login(int sockfd,data_t cdata,struct sockaddr_in caddr);//登录
void send_t(int sockfd,data_t data,struct sockaddr_in saddr);//发送信息
void line(int sockfd,data_t cdata,struct sockaddr_in caddr);//下线int main(int argc, char *argv[])
{
if(argc!=2)
printf("请正确输入: ./client IP号\n");/**************** 1、创建套接字 -- socket *********************/int sockfd = socket(AF_INET, SOCK_DGRAM, 0);/****************2、绑定IP地址和端口号 -- bind ****************/struct sockaddr_in saddr, caddr;caddr.sin_family = AF_INET;caddr.sin_port = htons(8888);//将主机字节序转换为网络字节序再赋值caddr.sin_addr.s_addr = inet_addr(argv[1]);int s_len = sizeof(saddr);/**************** 3、发送接送数据 *****************************/data_t cdata={0,0,0},sdata={0,0,0};//定义收发数据结构体int d_len=sizeof(cdata);//计算数据结构体长度memset(&saddr, 0,s_len);//清空接收地址结构memset(&cdata, 0,d_len);//清空接收地址结构signal(SIGCHLD, mysignal);//捕获子进程释放信号pid_t pid=fork();//创建线程if(0==pid)//子线程{printf("请输入你的用户名--->");fgets(cdata.name,64,stdin);//获取输入进来的名字cdata.name[strlen(cdata.name)-1] = '\0';//删除获取进来的回车'\n'login(sockfd,cdata,caddr);//登录while(1){fgets(cdata.text,64,stdin);//获取输入进来的内容cdata.text[strlen(cdata.text)-1] = '\0';//删除获取进来的回车'\n'if(strcmp(cdata.text,"line!!!")==0) //判断是否结束聊天line(sockfd,cdata,caddr);//下线       send_t(sockfd,cdata,caddr);//聊天}}while(1){ memset(&sdata, 0, d_len);//清空接送到的数据recvfrom(sockfd, &sdata, d_len, 0, (struct sockaddr*)&saddr, &s_len);if(strcmp(sdata.type,"send_t")==0)//在客户端中显示接送到的消息printf("%s:%s\n",sdata.name,sdata.text);else    printf("%s-->%s\n",sdata.name,sdata.text);}/**************** 4、关闭套接字 *******************************/close(sockfd);return 0;
} /**************** 登录 ***************************************/
void login(int sockfd,data_t cdata,struct sockaddr_in caddr)//登录
{int d_len = sizeof(cdata);int s_len = sizeof(caddr);strcpy(cdata.type,"login");strcpy(cdata.text,"上线了");sendto(sockfd, &cdata, d_len, 0, (struct sockaddr*)&caddr, s_len);
}/**************** 下线 ***************************************/
void line(int sockfd,data_t cdata,struct sockaddr_in caddr)//下线
{int d_len = sizeof(cdata);int s_len = sizeof(caddr);strcpy(cdata.type,"line");strcpy(cdata.text,"下线了");sendto(sockfd, &cdata, d_len, 0, (struct sockaddr*)&caddr, s_len);exit(0);
}/**************** 聊天 ***************************************/
void send_t(int sockfd,data_t cdata,struct sockaddr_in caddr)//发送信息
{int ret=0;int d_len = sizeof(cdata);int s_len = sizeof(caddr);strcpy(cdata.type,"send_t");ret = sendto(sockfd, &cdata, d_len, 0, (struct sockaddr*)&caddr, s_len);
}

基于UDP的简易多人聊天室相关推荐

  1. python实现简易聊天需要登录博客园zip下载_Python基于Socket实现简易多人聊天室的示例代码...

    前言 套接字(Sockets)是双向通信信道的端点. 套接字可以在一个进程内,在同一机器上的进程之间,或者在不同主机的进程之间进行通信,主机可以是任何一台有连接互联网的机器. 套接字可以通过多种不同的 ...

  2. 网络编程套接字(上篇)UDP实现简易多人聊天室

    目录 背景知识 主机间通信本质 socket 端口号特点: 为什么不用进程pid? 网络字节序 socket编程接口API sockaddr结构 ​编辑 简单UDP网络程序 了解UDP协议 简易多人聊 ...

  3. 基于UDP的dos多人聊天室

    文章目录 ##前言 \qquad这学期正好有门TCP/IP 编程,乘机写了个dos下的聊天室,去年这个时候用Java写了个带GUI的多人聊天室,不过整体来看这次在对网络编程有了一定的理论基础后,这次用 ...

  4. python多人聊天室_Python基于Socket实现简易多人聊天室

    前言 套接字(Sockets)是双向通信信道的端点. 套接字可以在一个进程内,在同一机器上的进程之间,或者在不同主机的进程之间进行通信,主机可以是任何一台有连接互联网的机器. 套接字可以通过多种不同的 ...

  5. Java Socket实现简易多人聊天室传输聊天内容或文件

    Java Socket实现简易多人聊天室传输聊天内容或文件 Java小练手项目:用Java Socket实现多人聊天室,聊天室功能包括传输聊天内容或者文件.相比于其它的聊天室,增加了传输文件的功能供参 ...

  6. JAVA网络编程NIO实现简易多人聊天室

    BIO模型 BIO即blocking IO,顾名思义是一种阻塞模型.当没有客户端连接时,服务端会一直阻塞,当有客户端新建连接时,服务端会新开一个线程去响应(不用多线程的话服务端同一时刻最多只能接收一个 ...

  7. java 网络编程 聊天_Java——网络编程(实现基于命令行的多人聊天室)

    目录: 1.ISO和TCP/IP分层模型 2.IP协议 3.TCP/UDP协议 4.基于TCP的网络编程 5.基于UDP的网络编程 6.基于TCP的多线程的聊天室的实现 1.ISO和TCP/IP分层模 ...

  8. Java——网络编程(实现基于命令行的多人聊天室)

    2019独角兽企业重金招聘Python工程师标准>>> 目录: 1.ISO和TCP/IP分层模型 2.IP协议 3.TCP/UDP协议 4.基于TCP的网络编程 5.基于UDP的网络 ...

  9. Java TCP简易多人聊天室

    一.说明: ​ 本例是一个简易的Java TCP多人聊天室,先启动服务器端,再启动客户端,客户端敲入用户名,然后可以开始聊天,敲入信息,每一个在线的用户都会收到相应信息. 演示如下图: 二.服务器端代 ...

最新文章

  1. lambda在python中的用法_在python中对lambda使用.assign()方法
  2. STL Algorithms 之 unique
  3. mongodb性能分析方法:explain()
  4. GCN(一)数据集介绍
  5. echarts各种事件
  6. 安装ElasticSearch过程遇到的坑
  7. TINYBERT: DISTILLING BERT FOR NATURAL LANGUAGE UNDERSTANDING
  8. zz机器学习与人工智能学习资源导引
  9. unix网络编程之基本套接口编程
  10. 关于ITIL4 认证你必须了解的知识
  11. 计算机清理方法,电脑清理方法 电脑要如何清理
  12. 电机控制基础知识储备
  13. HTML+CSS+JS网页设计期末课程大作业:中华传统文化主题设计题题材【非遗文化14页】 web前端开发技术 web课程设计 网页规划与设计
  14. java中如何求101-200之间的素数,并统计素数个数
  15. android 新闻功能列表,news: 用Android基本技术实现的新闻App
  16. 2 GateWay工作流程+GateWay搭建
  17. 微信支付开发教程(公众号支付)
  18. 记录Java Steam流的一些用法
  19. 2023年美赛数学模型与思路 美国大学生数学建模竞赛
  20. AI绘图工具--Midjourney使用指南

热门文章

  1. 软件测试考研究生课程,考研学霸必备的9款学习APP,亲测好用
  2. 一款强大到没朋友的图片编辑插件,爱了爱了!
  3. Kickstarter | 海外众筹项目汇总
  4. 网络空间安全---漏洞基础知识
  5. 正则表达式与corn表达式
  6. C语言与MYSQL数据库的连接
  7. 七周二次课(5月7日)
  8. 大学生考证:全国计算机等级测试
  9. 前馈神经网络_BP算法+R语言程序运行实例
  10. 物联网传感技术——传感器的一般特性