基于(LinuxC语言)的UDP局域网聊天室
功能:
1)用户登录提示.
2)服务器转发客户端发来的消息给其他客户端.
3)当前客户端输入quit可以退出自己,并且服务器转发退出提示.
4)服务器会转发自己从终端输入的内容给所有客户端.
注意:
1)服务器端需要命令行传参的方式输入端口号.
2)客户端需要命令行传参的方式输入ip地址以及端口号.
3)因为我懒并未设置 “客户端ctrl+c”等信号 退出客户会转发用户退出的功能(你想的话可以在服务器端signal接收下信号,并设置处理方式).
4)本程序用“fork函数”以多进程的方式实现多路复用,请注意.
5)本聊天室仅限于同一网段内进行通信.
6)因为我是一个人测试的,所以重复我是根据端口号来判断的,后面因为懒又不想改了,你们可以改为姓名判断或者是ip判断的.
代码:
注:本人较懒,所以注释有点少
服务器端:
#include<stdio.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <unistd.h>
#include<stdlib.h>
typedef struct
{char name[32]; char text[256];
}MSG;
typedef struct sockadd
{struct sockaddr_in data;struct sockadd *next;
}sock_t;/***************************注意,接收的消息第一个字符代表类型,‘n’为名字,代表用户登录‘t’为消息,代表是用户发的消息*///创建表头
sock_t *cret_sockadd(void)
{sock_t *p=(sock_t *)malloc(sizeof(sock_t));if(NULL==p){perror("sockadd err.");return NULL;}p->next=NULL;return p;
}//用户退出删除用户
void del_sock(sock_t *p,int sockfd,struct sockaddr_in a,char msg[])
{char buf[32]="",quit[]="quit";strncpy(buf,msg+1,1);strcat(buf," sir exit chat.");sock_t *pdel=NULL;sock_t *pt=NULL;sock_t *q=p;while(p->next!=NULL){pt=p;p=p->next;if(p->data.sin_port==a.sin_port){sendto(sockfd,quit,sizeof(quit),0,(struct sockaddr *)&p->data,sizeof(p->data));pdel=p;pt->next=pdel->next;free(pdel);pdel=NULL;puts(buf);while(q->next!=NULL){q=q->next;sendto(sockfd,buf,sizeof(buf),0,(struct sockaddr *)&(q->data),sizeof(q->data));}}}
}//添加用户
int add_sock(sock_t *p,struct sockaddr_in a)
{while(p->next!=NULL)p=p->next;sock_t *pnew=(sock_t *)malloc(sizeof(sock_t));if(NULL==pnew){perror("pnew malloc err.");return -1;}pnew->data=a;pnew->next=p->next;p->next=pnew;return 0;
}int main(int argc, const char *argv[])
{int i;sock_t *p=cret_sockadd();MSG msg;int sockfd=socket(AF_INET,SOCK_DGRAM,0);if(sockfd<0){perror("socket err.");return -1;}struct sockaddr_in servcr;servcr.sin_family=AF_INET;servcr.sin_port=htons(atoi(argv[1]));servcr.sin_addr.s_addr=htonl(INADDR_ANY);struct sockaddr_in clint;socklen_t len=sizeof(clint);char buf[32];if(bind(sockfd,(struct sockaddr *)&servcr,sizeof(servcr))<0){perror("bind err.");return -1;}pid_t pid=fork();if(pid<0){perror("fork err.");return -1;}else if(pid==0) //子进程,自己发消息给父进程,然后父进程转发消息给客户{char temp[256]="";while(1){bzero(temp,sizeof(temp));bzero(buf,sizeof(buf));fgets(buf,32,stdin);if(buf[strlen(buf)-1]=='\n')buf[(strlen(buf)-1)]='\0';strcat(temp,"tFuWuqi say:");strcat(temp,buf);sendto(sockfd,temp,sizeof(temp),0,(struct sockaddr *)&servcr,sizeof(servcr));}}else{while(1){bzero(&msg,sizeof(msg));recvfrom(sockfd,msg.text,sizeof(msg.text),0,(struct sockaddr *)&clint,&len);if(strcmp(&(msg.text[strlen(msg.text)-4]),"quit")==0){del_sock(p,sockfd,clint,msg.text);continue;}if(msg.text[0]=='n') //接收的消息第一个字符如果是n代表用户登录{add_sock(p,clint); sock_t *q=p;printf("%s login\n",msg.text+1);printf("=================\n");strcat(msg.text," login");while(q->next!=NULL){q=q->next;if(q->data.sin_port==clint.sin_port)//不给自己发消息continue;sendto(sockfd,msg.text+1,sizeof(msg.text),0,(struct sockaddr *)&(q->data),sizeof(q->data));}q=NULL;continue;//跳过服务器打印消息}else if(msg.text[0]=='t')//如果是t,代表是消息{sock_t *x=p;while(x->next!=NULL)//转发给其他用户{x=x->next;if(x->data.sin_port==clint.sin_port)//跳过自己continue;sendto(sockfd,msg.text+1,sizeof(msg.text),0,(struct sockaddr *)&(x->data),sizeof(x->data));}x=NULL;}printf("%s\n",(msg.text+1)); //服务器打印消息 printf("=================\n");}wait(NULL);}free(p);p=NULL;close(sockfd);return 0;
}
客户端:
#include<stdio.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <unistd.h>#include <stdlib.h>
typedef struct
{char name[32];char text[256];
}MSG;int main(int argc, const char *argv[])
{int sockfd=socket(AF_INET,SOCK_DGRAM,0);if(sockfd<0){perror("socket err.");return -1;}struct sockaddr_in servcr;servcr.sin_family=AF_INET;servcr.sin_port=htons(atoi(argv[2]));servcr.sin_addr.s_addr=inet_addr(argv[1]);socklen_t len=sizeof(servcr);MSG msg;int s=0;char buf[128]="";msg.name[0]='n'; //把发送的消息第一位赋值‘n’,代表是用户登录printf("please input your name:");fgets(msg.name+1,31,stdin); //发消息的第一位变为标志位,所以从第二位开始输入if(msg.name[strlen(msg.name)-1]=='\n') //因为fgets会多一个‘\n’,把其覆盖掉msg.name[(strlen(msg.name)-1)]='\0';int a=sendto(sockfd,msg.name,32,0,(struct sockaddr *)&servcr,sizeof(servcr));//发送登录用户名strcat(msg.name," say:"); //名字与say拼接起来pid_t pid=fork();if(pid<0){perror("fork err.");return -1;}else if(pid==0){while(1){if(s==1) //如果用户退出会把s置1表示用户退出,这时候结束子进程break;bzero(msg.text,sizeof(msg.text));bzero(buf,sizeof(buf));msg.name[0]='t'; //把标志位为‘t’,代表发送的是消息,会覆盖掉‘n’或者‘t’,消息不受影响printf("Please input:");fflush(NULL);fgets(buf,sizeof(msg.text),stdin);if(buf[strlen(buf)-1]=='\n')buf[(strlen(buf)-1)]='\0';if(strcmp(buf,"quit")==0)s=1;strcat(msg.text,msg.name);//把xx说与发送的消息拼接起来strcat(msg.text,buf); //发送quit,服务器收到会删除用户sendto(sockfd,msg.text,256,0,(struct sockaddr *)&servcr,sizeof(servcr));}exit(0);}else{while(1){bzero(msg.text,sizeof(msg.text));recvfrom(sockfd,msg.text,sizeof(msg.text),0,(struct sockaddr *)&servcr,&len);puts("");puts("=================");if(strcmp(msg.text,"quit")==0) //子进程结束后会跳出,父进程会接收到quit,然后退出进程break;printf("%s\n",msg.text);puts("=================");}wait(NULL);}close(sockfd);return 0;
}
emmm,有很多方面我做的并不是很好,还有其他解决方法,你可以使用别样的方法完成,如果这里有啥做的不对的,欢迎各位大佬帮忙指正,小白在这里感谢,最后,让我们一起加油,一起努力,未来可期!
基于(LinuxC语言)的UDP局域网聊天室相关推荐
- 基于Java语言的Web在线聊天室
在线聊天室 能够实现登录,注册,聊天功能,最终效果如下图所示 注册页面 <%@ page language="java" contentType="text/htm ...
- java毕业设计——基于java+TCP+UDP的局域网聊天室系统设计与实现(毕业论文+程序源码)——局域网聊天室系统
基于java+TCP+UDP的局域网聊天室系统设计与实现(毕业论文+程序源码) 大家好,今天给大家介绍基于java+TCP+UDP的局域网聊天室系统设计与实现,文章末尾附有本毕业设计的论文和源码下载地 ...
- python实现简易聊天需要登录博客园zip下载_Python基于Socket实现简易多人聊天室的示例代码...
前言 套接字(Sockets)是双向通信信道的端点. 套接字可以在一个进程内,在同一机器上的进程之间,或者在不同主机的进程之间进行通信,主机可以是任何一台有连接互联网的机器. 套接字可以通过多种不同的 ...
- 基于Node.js + WebSocket 的简易聊天室
代码地址如下: http://www.demodashi.com/demo/13282.html Node.js聊天室运行说明 Node.js的本质就是运行在服务端的JavaScript.Node.j ...
- 基于Linux下的即时通讯聊天室项目(全代码 有注释 可直接运行)
基于Linux下的即时通讯聊天室项目 一.序言 二.具体功能 三.系统客户要求 四.具体代码 1.服务器代码 2.客户端代码 一.序言 最近在写一个基于Linux下的聊天工具 它适合于局域网内所有人进 ...
- 【java毕业设计】基于java+原生Sevlet+socket的聊天室系统设计与实现(毕业论文+程序源码)——聊天室系统
基于java+原生Sevlet+socket的聊天室系统设计与实现(毕业论文+程序源码) 大家好,今天给大家介绍基于java+原生Sevlet+socket的聊天室系统设计与实现,文章末尾附有本毕业设 ...
- 视频教程-实战Go语言:多人聊天室-Go语言
实战Go语言:多人聊天室 多年互联网从业经验: 有丰富的的企业网站.手游.APP开发经验: 曾担任上海益盟软件技术股份有限公司项目经理及产品经理: 参与项目有益盟私募工厂.睿妙影音家庭物联网设备.手游 ...
- 局域网服务器发送消息,Java实现简单局域网聊天室
本文实例为大家分享了Java实现简单局域网聊天室的具体代码,供大家参考,具体内容如下 Java 的Socket编程: 1.TCP协议是面向连接的.可靠的.有序的.以字节流的方式发送数据,通过三次握手方 ...
- 实战Go语言:多人聊天室-欧阳桫-专题视频课程
实战Go语言:多人聊天室-77人已学习 课程介绍 ·基于Go的网络和并发技术开发多人在线聊天室: ·功能包括:单聊.群聊.昵称.上下线通知.聊天日志等: ·技术栈:TCP通信.协程并发 ...
- 基于C/S模式的简单聊天室
基于C/S模式的简单聊天室 要求: 使用Socket实现网上聊天室,要求基于TCP或UDP协议,用户可以通过客户端连接到服务器端并进行聊天,聊天时可以启动多个客户端:服务器启动后,接收客户端发来的用户 ...
最新文章
- [算法]链表的逆序遍历节点
- 使用 SetCustomizedString汉化UltraWinGrid的筛选
- Python基础语法-三种函数特殊形参定义以及使用方式
- java 接口不是不能new吗?- java:使用匿名类直接new接口
- ld 用法:gcc 过程最后一步-链接
- 大数据发展火爆,云计算平台主打安全至上
- 以为GAN只能“炮制假图”?它还有这7种另类用途
- Hive分区(静态分区+动态分区)
- 管理新语:工作没做好,批评几句,怎么成了诛心
- 计算机进pe按键,win10下进入pe系统操作方法
- python logging日志分割_Python3测井曲线切割,python3logging,日志
- 计算机课堂有趣的游戏,有趣的课堂游戏作文范文5篇
- Multisim里导入没有的元器件(以NPN型三极管2N9013为例)
- 数字信号处理中均值、均方值、均方差、均方根值、均方误差、均方根误差、方差、协方差、标准差对比分析及统计学意义
- 北京知产局:鼓励当事人用区块链,获取、固定知识产权纠纷证据
- 10个方法教你提升表达能力
- 勋章菊的养殖方法和注意事项
- Excel·VBA按行拆分工作表
- android 蓝牙电话号码,Android拨打电话和蓝牙状态监听
- 原来华为手机的语音助手这么好用,说话即可语音翻译,方便又实用