使用UDP协议构建简易局域网内聊天室
实现功能:
客户端
1.开启时输入昵称并往服务器端发送带有客户端昵称
2.开启后能随时往服务器端发送聊天内容
3.收到服务器发来的数据时判别是否为自己发送的数据,若不是则输出num编号所指引的内容
4. 当输入quit时退出
服务器
1.接受各个客户端的信息,新用户则将其存入链表中并向各个用户发送有新用户加入的信息
2.当用户输入quit时,删除该用户信息并向各个用户发送该用户退出的信息
3.当收到正常聊天信息时发送给各个用户
代码
客户端
客户端中ip设定为本机的ip地址,通过外部传参传入不同的端口号用以区分不同用户
#include <sys/types.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>
#define ERR_MSG(msg) do {\fprintf(stderr,"_%d_",__LINE__);\perror(msg);\
}while(0)
#define IP "192.168.31.242"
//#define PORT 8888 // 1024~49151
typedef struct MSG{int num;char name[20];char data[256];
}MSG;int sfd;
struct sockaddr_in cin;
socklen_t addrlen= sizeof(cin);
MSG msg;
char cname[20];
void *shou(void*arg)
{while(1){if(recv(sfd, &msg, sizeof(msg),0) < 0){ERR_MSG("recvfrom");return NULL;}if (strcmp(msg.name,cname)!=0) //判断是否为自己发送的{if(msg.num==3){printf("%s:%s\n",msg.name,msg.data);}if (msg.num==4){printf("%s进入聊天室\n",msg.name);}}}pthread_exit(NULL);}void *fa(void*arg)
{while(1){scanf("%s",msg.data);msg.num=2;strcpy(msg.name,cname);if(sendto(sfd, &msg, sizeof(msg), 0, (struct sockaddr*)&cin, sizeof(cin)) < 0){ERR_MSG("recvfrom");return NULL;}if (strcmp(msg.data,"quit")==0){exit(0);}}pthread_exit(NULL);}//绑定一个广播ip的端口试试int main(int argc, const char *argv[])
{//创建报式套接字sfd =socket(AF_INET,SOCK_DGRAM,0);if (sfd<0){ERR_MSG("socket");return -1;}printf("create socket success\n");int broad =1;if (setsockopt(sfd,SOL_SOCKET,SO_BROADCAST,&broad,sizeof(broad))<0){ERR_MSG("setsockopt");return -1;}//填充地址信息结构体,真实的地址信息结构体与协议族有关//AF_INEt 详见 man 7 ipstruct sockaddr_in sin;sin.sin_family =AF_INET;sin.sin_port =htons(8888);//主机字节序转网络字节序的端口号sin.sin_addr.s_addr = inet_addr("192.168.31.255");cin = sin;int port = atoi(argv[1]);struct sockaddr_in bin;bin.sin_family =AF_INET;bin.sin_port =htons(port);//主机字节序转网络字节序的端口号bin.sin_addr.s_addr = inet_addr(IP);if(bind(sfd,(struct sockaddr*)&bin,sizeof(bin))==-1){ERR_MSG("bind");return -1;}ssize_t res=0;printf("请输入用户名:");scanf("%s",msg.name);msg.num=1;//num为1时内容为名字strcpy(cname,msg.name);sendto(sfd,&msg,sizeof(msg),0,(struct sockaddr*)&sin, addrlen);msg.num=2; //num为2时内容为聊天内容//将客户端的收发分别写入两个线程,这样就可以同时运行pthread_t tid1,tid2;if (pthread_create(&tid1,NULL,shou,NULL)!=0){ERR_MSG("pthread_create");return -1;}if (pthread_create(&tid2,NULL,fa,NULL)!=0){ERR_MSG("pthread_create");return -1;}pthread_join(tid1,NULL);pthread_join(tid2,NULL);close(sfd);return 0;
}
服务器端
#include <sys/types.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#define ERR_MSG(msg) do {\fprintf(stderr,"_%d_",__LINE__);\perror(msg);\
}while(0)typedef struct MSG{int num;char name[20];char data[256];}MSG;MSG msg;
int sfd;
struct sockaddr_in cin;
socklen_t addrlen= sizeof(cin);typedef struct Node{union{int len;struct sockaddr_in nin;}; struct Node * next;
}List; //定义一个链表用于存放用户信息int main(int argc, const char *argv[])
{//创建报式套接字sfd =socket(AF_INET,SOCK_DGRAM,0);if (sfd<0){ERR_MSG("socket");return -1;}printf("create socket success\n");int broad =1;if (setsockopt(sfd,SOL_SOCKET,SO_BROADCAST,&broad,sizeof(broad))<0){ERR_MSG("setsockopt");return -1;}MSG msg;//填充地址信息结构体,真实的地址信息结构体与协议族有关//AF_INEt 详见 man 7 ipstruct sockaddr_in sin;sin.sin_family =AF_INET;sin.sin_port =htons(8888);//主机字节序转网络字节序的端口号sin.sin_addr.s_addr = inet_addr("192.168.31.255");if (bind(sfd,(struct sockaddr *)&sin,sizeof(sin))<0){ERR_MSG("bind");return -1;}List *l= (List*)malloc(sizeof(List));if (NULL==l){ERR_MSG("malloc");return -1;}l->len=0;l->next=NULL;List * p =NULL;List * q=NULL;ssize_t res=0;while (1){res = recvfrom(sfd,&msg,sizeof(msg),0,(struct sockaddr*)&cin,&addrlen); if(res == -1){ERR_MSG("recvfrom");return -1;}else if (res>0)//读取成功{if (msg.num==1)//新用户,需a要写入链表{printf("[%s:%d]\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port));//使用头插将新用户插入链表中p= (List*)malloc(sizeof(List));if (NULL==p){ERR_MSG("malloc");return -1;}p->next=l->next;p->nin=cin;l->next=p;l->len++;q=l->next;//广播有新的用户进入聊天msg.num=4;//防止自己收到后继续输出while(q!=NULL){if(sendto(sfd,&msg,sizeof(msg),0,(struct sockaddr*)&q->nin,sizeof(q->nin))<0){ERR_MSG("sendto");return -1;}q=q->next;}}else if(msg.num==2)//老用户{printf("[%s:%d]\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port));if (strcmp(msg.data,"quit")==0)//用户退出,需要广播退出信息并将其在链表中删除{msg.num=3;strcpy(msg.data,"已退出");q=l->next;while(q!=NULL){if(sendto(sfd,&msg,sizeof(msg),0,(struct sockaddr*)&q->nin,sizeof(q->nin))<0){ERR_MSG("sendto");return -1;}q=q->next;}p=l;while (p->next!=NULL){if (p->next->nin.sin_port == cin.sin_port){q=p->next->next;free(p->next);p->next=q;break;}p=p->next;}//将该用户在链表中删除}else{//正常聊天广播收到的内容msg.num =3;//防止自己收到后继续输出q=l->next;while(q!=NULL){if(sendto(sfd,&msg,sizeof(msg),0,(struct sockaddr*)&q->nin,sizeof(q->nin))<0){ERR_MSG("sendto");return -1;}q=q->next;}}}}}close(sfd);return 0;
}
运行测试 :
成功完成预计功能。
使用UDP协议构建简易局域网内聊天室相关推荐
- python实现简易聊天需要登录_python编写简易聊天室实现局域网内聊天功能
本文实例为大家分享了python实现局域网内聊天功能的具体代码,供大家参考,具体内容如下 功能: 可以向局域网内开启接收信息功能的ip进行发送信息,我们可以写两段端口不同的代码来实现在一台电脑上与自己 ...
- python语言视频-Python语言之Python3 实现简易局域网视频聊天工具
本文主要向大家介绍了Python语言之Python3 实现简易局域网视频聊天工具,通过具体的内容向大家展示,希望对大家学习Python语言有所帮助. 操作系统为 Ubuntu 16.04,OpenCV ...
- 网络编程套接字(上篇)UDP实现简易多人聊天室
目录 背景知识 主机间通信本质 socket 端口号特点: 为什么不用进程pid? 网络字节序 socket编程接口API sockaddr结构 编辑 简单UDP网络程序 了解UDP协议 简易多人聊 ...
- Python3 实现简易局域网视频聊天工具
Python3 实现简易局域网视频聊天工具 1.环境 操作系统为 Ubuntu 16.04 python 3.5 opencv-python 3.4.1.15 numpy 1.14.5 PyAudio ...
- 利用TCP/UDP 协议制作一个飞秋聊天工具
视频操作演示: 利用TCP/UDP 协议制作一个飞秋聊天工具演示视频 int udp_broadcast(char const*argv[]) {//1.创建对象udp_socket = socket ...
- python实现简易聊天需要登录博客园zip下载_Python基于Socket实现简易多人聊天室的示例代码...
前言 套接字(Sockets)是双向通信信道的端点. 套接字可以在一个进程内,在同一机器上的进程之间,或者在不同主机的进程之间进行通信,主机可以是任何一台有连接互联网的机器. 套接字可以通过多种不同的 ...
- 基于TCP协议的mfc多人聊天室
基于TCP协议的MFC多人聊天室 简易的mfc聊天室思路实现 前言 一.socket通信 二.效果展示 三.代码实现 1.ClientSocket.cpp 客户端套接字 2.ServerSocket. ...
- JAVA网络编程NIO实现简易多人聊天室
BIO模型 BIO即blocking IO,顾名思义是一种阻塞模型.当没有客户端连接时,服务端会一直阻塞,当有客户端新建连接时,服务端会新开一个线程去响应(不用多线程的话服务端同一时刻最多只能接收一个 ...
- Java Socket实现简易多人聊天室传输聊天内容或文件
Java Socket实现简易多人聊天室传输聊天内容或文件 Java小练手项目:用Java Socket实现多人聊天室,聊天室功能包括传输聊天内容或者文件.相比于其它的聊天室,增加了传输文件的功能供参 ...
最新文章
- Win10控制桌面图标显示
- DevOps简单介绍
- ATL的GUI程序设计(前言)
- caffe提取每一层中的特征,在matlab或python查看
- 深度学习基础(二)—— 从多层感知机(MLP)到卷积神经网络(CNN)
- 感谢大家的热情与温暖
- 多个客户端共用同一条拉起链接 ,如何配置 Universal Link iOS App
- C++11模板友元语法
- 经验分享:我是如何在网店无货源情况下快速出单?
- d3开发Svg编辑器
- 批处理批量卸载微软补丁
- 用友u8怎么导出凭证_老师,用友U8里的凭证如何导出(导出有借贷方向的)?...
- 微信公众号首次关注自动回复图文信息
- 怎样用python制表_用Python绘图和制表(附泰坦尼克号案例)
- MPC+HSM造就了安全的数字托管人
- 【算法】求解钱币兑换问题
- 郭炜:CTO、技术VP、技术总监、首席架构师的区别?
- TypeError: e[h] is not a function
- 若依框架---分页功能
- Python 验证Mac地址