1.实验项目名称:基于Linux的TCP网络聊天室

2.实验目的:通过TCP完成多用户群聊和私聊功能。

3.实验过程:

通过socket建立用户连接并传送用户输入的信息,分别来写客户端和服务器端,利用多线程来实现多用户模式,服务器端随时准备接收客户端发送的消息,并判断该消息类型(私聊或群聊)来进行对应的转发工作,客户端随时接受来自服务器端的消息,从而实现消息的同步。

(1)开启服务器。

(2)开启客户端,输入用户昵称,客户端开始与服务器建立连接。

(3)群聊功能,一名用户发送消息,聊天室的其他成员均可收到此消息。

(4)私聊功能,一位用户@其他用户,则此消息只有被@的用户可以收到。

用户的信息借助结构体来存放,群聊功能通过遍历结构体,把消息发送给每一名用户,私聊功能通过对用户所发消息进行判断,若消息中存在@其他用户则把该消息私发给指定用户。

另外,私聊功能函数可以进行对各种@操作的判断,如用户所@的人不存在,则把此消息作为群消息发出,@其他用户后没有添加空格,则把此消息视为群发消息。

源码:

头文件

 1 //header.h
2 #ifndef _A_H
3 #define _A_H
4 #include <stdio.h>
5 #include <pthread.h>
6 #include <sys/socket.h>
7 #include <netinet/in.h>
8 #include <arpa/inet.h>
9 #include <stdlib.h>
10 #include <unistd.h>
11 #include <string.h>
12 #include <signal.h>
13 #include <pthread.h>
14 struct client{
15 char name[30]; //客户端名字
16 int fds; //客户端socket描述符
17 };
18 struct client c[100]={0};//接收客户端100个
19 int in; //数组下标
20 char *IP ="127.0.0.1"; //ip
21 short PORT=10222;
22 char NAME[20]={}; //@的名字
23 int FLAG=0; //标记是群发还是私聊
24 #endif

服务器端

 1 //tcp_s.c
2 #include "header.h"
3 int sockfd; //服务器socket
4 char tempName[20]={};
5 //初始化服务器网络
6 void init(){
7 printf("start chat room...");
8 sockfd = socket(PF_INET,SOCK_STREAM,0);
9 if(sockfd == -1){
10 perror("create socket false\n");
11 exit(-1);
12 }
13 struct sockaddr_in addr; //网络通信地址结构
14 addr.sin_family = PF_INET; //协议簇
15 addr.sin_port = htons(PORT); //端口
16 addr.sin_addr.s_addr = inet_addr(IP); //IP地址
17 if(bind(sockfd,(struct sockaddr*)&addr,sizeof(addr)) == -1){
18 perror("bind false\n");
19 exit(-1);
20 }
21 if(listen(sockfd,100) == -1){
22 perror("Setup listening failed\n");
23 exit(-1);
24 }
25 printf("Server initialization succeeded!\n");
26 }

分发消息

 1 void SendMessage(char *msg){
2 int flag=0; //标记@符号是否为私聊
3 int exit=0; //比较@的用户是否存在
4 int i=0,j=0;
5 while(msg[i]!=':'){
6 if(i>=strlen(msg))
7 break;
8 i++;
9 } //找到@符号位置
10 if(msg[i+1] == '@'){
11 i++;
12 while(msg[i]!=32){
13 if(i>=strlen(msg)){ //@符号不是私聊作用
14 flag=1;
15 break;
16 }
17 NAME[j]=msg[i+1];
18 i++;
19 j++;
20 }
21 if(flag){ //群发
22 for(i=0;i<in;i++){
23 printf("send to %d\n",c[i].fds);
24 send(c[i].fds,msg,strlen(msg),0);
25 }
26 }
27 else{ //私发
28 for(i=0;i<in;i++){
29 int k=0;
30 for(k=0;k<strlen(NAME)-1;k++){
31 tempName[k]=NAME[k];
32 }
33 if(strcmp(c[i].name,tempName)==0){
34 send(c[i].fds,msg,strlen(msg),0);
35 exit=1;
36 break;
37 }
38 }
39 }
40 }
41 else{
42 exit = 1;
43 for(i=0;i<in;i++){
44 printf("send to %d\n",c[i].fds);
45 send(c[i].fds,msg,strlen(msg),0);
46 }
47 }
48 if(exit == 0){
49 for(i=0;i<in;i++){
50 printf("send to %d\n",c[i].fds);
51 send(c[i].fds,msg,strlen(msg),0);
52 }
53 }
54 }

线程函数中进行通信/接收客户端消息,分发给所有客户端 

 1 void *server_thread(void *p){
2 char name[30]={};
3 if(recv(c[in].fds,name,sizeof(name),0)>0){
4 name[strlen(name)]='\0';
5 strcpy(c[in].name,name);
6 }
7 in++;
8 char tip[100]={};
9 sprintf(tip,"%s join in the chat room\n",c[in-1].name);
10 SendMessage(tip);
11 int fd = *(int*)p;
12 printf("pthread = %d\n",fd);
13 while(1){
14 char buf[100]={};
15 if(recv(fd,buf,sizeof(buf),0) == 0){
16 //表示退出连接
17 printf("fd = %d left the chat room\n",fd);
18 int i,j;
19 char name[20]={};
20 int flag = 1;
21 for(i=0;i<in;i++){
22 if(c[i].fds == fd){
23 strcpy(name,c[i].name);
24 i++;
25 flag = 0;
26 }
27 if(flag != 1){
28 c[i-1].fds = c[i].fds;
29 strcpy(c[i-1].name,c[i].name);
30 }
31 }
32 c[i].fds = 0;
33 strcpy(c[i].name,"");
34 in--;
35 char msg[100];
36 sprintf(msg,"%s left the chat room\n",name);
37 SendMessage(msg);
38 close(fd);
39 break;
40 }
41 SendMessage(buf);
42 }
43 }

等待客户端连接,启动服务器的服务

 1 void server(){
2 printf("Server starts service!\n");
3 while(1){
4 struct sockaddr_in fromaddr; //存储客户端通信地址
5 socklen_t len = sizeof(fromaddr);
6 int fd = accept(sockfd,(struct sockaddr*)&fromaddr,&len);
7 if(fd == -1){
8 perror("Client connection failed!\n");
9 continue;
10 }
11 c[in].fds = fd;
12 pthread_t pid;
13 pthread_create(&pid,0,server_thread,&fd);
14 }
15 }
16 void sig_close(){
17 close(sockfd);
18 printf("Server close\n");
19 exit(0);
20 }
21 int main()
22 {
23 signal(SIGINT,sig_close);
24 init();
25 server();
26 return 0;
27 }

客户端

 1 //tcp_c.c
2 #include "header.h"
3 char name[30]; //name
4 int sockfd; //客户端socket
5 int mutax=0; //互斥变量
6 void init(){
7 printf("Client starts\n");
8 sockfd =socket(PF_INET,SOCK_STREAM,0);
9 struct sockaddr_in addr;
10 addr.sin_family =PF_INET;
11 addr.sin_port=htons(PORT);
12 addr.sin_addr.s_addr=inet_addr(IP);
13 if(connect(sockfd,(struct sockaddr*)&addr,sizeof (addr))==-1){
14 perror("connect failed\n");
15 exit(-1);
16 }
17 }

通信

 1 void start(){
2 pthread_t pid;
3 void* receive_thread(void*);
4 pthread_create(&pid,0,receive_thread,0);
5 while(1){
6 char buf[100]={};
7 gets(buf);
8 char msg[100]={};
9 if(mutax){
10 mutax=0;
11 continue;
12 }
13 sprintf(msg,"%s said:%s",name,buf);
14 send(sockfd,msg,strlen(msg),0);
15 }
16
17 }
18 void* receive_thread(void *p){
19 while(1){
20 char buf[100]={};
21 if(recv(sockfd,buf,sizeof(buf),0)<=0){
22 break;
23 }
24 printf("%s\n",buf);
25 }
26 }
27 void sig_close(){
28 close(sockfd);
29 exit(0);
30 }
31 int main(){
32 signal(SIGINT,sig_close);
33 printf("Please input your name:");
34 scanf("%s",name);
35 mutax=1;
36 init();
37 if(mutax)
38 send(sockfd,name,strlen(name),0);
39 start();
40 return 0;
41 }

基于Linux的TCP网络聊天室的更多相关文章

  1. 基于LINUX的多功能聊天室

    原文:基于LINUX的多功能聊天室 基于LINUX的多功能聊天室 其实这个项目在我电脑已经躺了多时,最初写完项目规划后,我就认认真真地去实现了它,后来拿着这个项目区参加了面试,同样面试官也拿这个项目来 ...

  2. Qt NetWork即时通讯网络聊天室(基于TCP)

    本文使用QT的网络模块来创建一个网络聊天室程序,主要包括以下功能: 1.基于TCP的可靠连接(QTcpServer.QTcpSocket) 2.一个服务器,多个客户端 3.服务器接收到某个客户端的请求 ...

  3. 网络编程TCP协议-聊天室

    网络编程TCP协议-聊天室(客户端与服务端的交互); <span style="font-size:18px;">1.客户端发数据到服务端.</span> ...

  4. Linux下TCP网络编程与基于Windows下C#socket编程间通信

    一.linux下TCP网络编程基础,需要了解相关函数 Socket():用于套接字初始化. Bind():将 socket 与本机上的一个端口绑定,就可以在该端口监听服务请求. Listen():使s ...

  5. php websocket-网页实时聊天之PHP实现websocket(ajax长轮询和websocket都可以时间网络聊天室)

    php websocket-网页实时聊天之PHP实现websocket(ajax长轮询和websocket都可以时间网络聊天室) 一.总结 1.ajax长轮询和websocket都可以时间网络聊天室 ...

  6. 基于EPOLL模型的局域网聊天室和Echo服务器

    一.EPOLL的优点 在Linux中,select/poll/epoll是I/O多路复用的三种方式,epoll是Linux系统上独有的高效率I/O多路复用方式,区别于select/poll.先说sel ...

  7. 基于 OpenResty 实现一个 WS 聊天室

    基于 OpenResty 实现一个 WS 聊天室 WebSocket WebSocket 协议分析 WebSocket 协议解决了浏览器和服务器之间的全双工通信问题.在WebSocket出现之前,浏览 ...

  8. Python3 网络通信 网络聊天室 文件传输

    Python3 网络通信 网络聊天室 文件传输 功能描述 该项目将实现一个文字和文件传输的客户端和服务器程序通信应用程序.它将传输和接收视频文件. 文本消息必须通过TCP与服务器通信,而客户端自己用U ...

  9. 基于Server-Sent Event的简单聊天室 Web 2.0时代,即时通信已经成为必不可少的网站功能,那实现Web即时通信的机制有哪些呢?在这门项目课中我们将一一介绍。最后我们将会实现一个基于Server-Sent Event和Flask简单的在线聊天室。

    基于Server-Sent Event的简单聊天室 Web 2.0时代,即时通信已经成为必不可少的网站功能,那实现Web即时通信的机制有哪些呢?在这门项目课中我们将一一介绍.最后我们将会实现一个基于S ...

随机推荐

  1. POJ2296二分2sat

    题意:       给n个点,每个点必须在一个正方形上,可以在正方向上面边的中点或者是下面边的中点,正方形是和x,y轴平行的,而且所有的点的正方形的边长一样,并且正方形不能相互重叠(边相邻可以),问满 ...

  2. 使用SSH端口做端口转发以及反向隧道

    目录 SSH做本地端口转发 SSH做反向隧道(远程端口转发) 用autossh建立稳定隧道 SSH开启端口转发需要修改 /etc/ssh/sshd_config配置文件,将 GatewayPorts修 ...

  3. JSON和JSONP的区别及使用方法

    JSON(JavaScript Object Notation)和JSONP(JSON with Padding)虽然只有一个字母的差别,但其实他们根本不是一回事儿:JSON是一种数据交换格式,而JS ...

  4. Jenkins 基础篇 - 环境准备

    前期准备 为了开发这套课程,我专门购买了一台二手戴尔服务器 Dell R720,同时把废弃多年的笔记本电脑也利用了起来.当然如果自己没有多余的电脑,也可以在自己电脑上安装 Vmware Worksta ...

  5. 【maven】pom.xml中"spring-boot-maven-plugin"报红问题

    问题原因 插件下载速度太慢了,即是从国外的中央仓库里下载的. 没有刷新maven spring-boot-maven-plugin没加版本号(有些电脑不加版本号,也是不会爆红的) 问题解决 maven ...

  6. 阿里面试官用HashMap把我问倒了

    本人是一名大三学生,最近在找暑期实习,其中也面试过两次阿里,一次菜鸟网络部门.一次网商银行部门,当然我都失败了,同时也让我印象很深刻,因此记录了其中一些面试心得,我觉得这个问题很值得分享,因此分享给大 ...

  7. springboot 项目中css js 等静态资源无法访问的问题

    目录 问题场景 问题分析 问题解决 问题场景 今天在开发一个springboot 项目的时候突然发现 css js 等静态资源竟然都报404找不到,折腾了好久终于把问题都解决了,决定写篇博客,纪录总结 ...

  8. Centos7下搭建gitbook环境踩坑记录

    1.安装npm yum -y install npm 2.配置npm仓 npm config set registry https://mirrors.tencent.com/npm/ 3.安装git ...

  9. If-Else 太多,如何优化!!!

    完全不必要的 Else 块 public void consumer(int product) { if (product > 1) { // do something } else { // ...

  10. Nifi:初识nifi

    写在前面: 第一次接触这一系统的时候,只有github上的一坨源码和官方的英文文档,用起来只能说是一步一个坑,一踩一个脚印,现在回想那段血泪史,只想 ***,现在用起来算是有了一些经验和总结,这里就做 ...