模拟QQ聊天,一个服务器处理多个客户端的连接,同时要求各个客户端之间能够自由通信。
本程序采用C/S架构,利用多线程完成。

服务器端:

a#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <pthread.h>#define PORT 8888 //设置端口号struct info     //定义结构体
{int ToFd;   //指定发送消息给谁char buf[100];  //消息内容
};/* 接收消息 */
void *MyReceive(void *arg)
{struct info RecvBuf;    //定义接收消息的缓冲区int ret;pthread_detach(pthread_self()); //线程分离while(1){ret = recv(*(int *)arg, &RecvBuf, sizeof(RecvBuf), 0);  //服务器接收来着一个客户端的消息if (-1 == ret){perror("recv");exit(1);}if (!strcmp(RecvBuf.buf, "bye"))    //如果接收到bye{close(*(int *)arg);     //关闭break;}ret = send(RecvBuf.ToFd, &RecvBuf, sizeof(RecvBuf), 0); //服务器转发收到的消息给指定的客户端if (-1 == ret){perror("send");exit(1);}memset(&RecvBuf, 0, sizeof(RecvBuf));   //清空缓冲区}
}int main()
{int sockfd, ret, fd[100] = {0}, length, i = 0;pthread_t tid[100] = {0};char buf[100] = {0};struct sockaddr_in server_addr; //用于存放服务器本身的信息,包括自己的端口号和IDstruct sockaddr_in client_addr; //接收客户端连接的时候,用于存放客户端信息printf("Start Server!\n");sockfd = socket(PF_INET, SOCK_STREAM, 0);   //创建socket,处理客户端的连接,不用于发送信息if (-1 == sockfd){perror("socket");exit(1);}memset(&server_addr, 0, sizeof(server_addr));server_addr.sin_family = PF_INET;   //地址族server_addr.sin_port = PORT;    //指定socket的端口号server_addr.sin_addr.s_addr = inet_addr("192.168.192.128"); //本机IPret = bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));   //上述信息绑定到socketif (-1 == ret){perror("bind");exit(1);}printf("Listening...\n");ret = listen(sockfd, 5);    //监听,是否有客户端发起连接if (-1 == ret){perror("listen");exit(1);}while(1){length = sizeof(client_addr);fd[i] = accept(sockfd,(struct sockaddr *)&client_addr, &length);    //接受客户端的连接,返回值用于发送信息if (-1 == fd[i]){perror("accept");exit(1);}printf("Accept %d, Port %d\n", fd[i], client_addr.sin_port);ret = pthread_create(&tid[i], NULL, MyReceive, (void *)&fd[i]); //创建线程if (0 != ret){perror("pthread_create");exit(1);}i++;}close(sockfd);return 0;
}

客户端:

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>#define PORT 8888   //设置端口号,与服务器一致struct info
{int ToFd;char buf[100];
};pthread_t tid[2] = {0};/* 发送消息 */
void *Send(void *arg)
{struct info SendBuf;int ret, oldtype;while(1){scanf("%s %d",SendBuf.buf, &SendBuf.ToFd);  //输入指定接收的客户端以及消息内容ret = send(*(int *)arg, &SendBuf, sizeof(SendBuf), 0);  //发送if (-1 == ret){perror("send");exit(1);}if (!strcmp("bye", SendBuf.buf))    //以bye结束{close(*(int *)arg);     //关闭该线程pthread_cancel(tid[1]); //同时取消该客户端用于接收消息的线程break;}memset(&SendBuf, 0, sizeof(SendBuf));}
}/* 接收消息 */
void *Receive(void *arg)
{struct info RecvBuf;int ret, oldtype;pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);   //设置线程取消的类型while(1){ret = recv(*(int *)arg, &RecvBuf, sizeof(RecvBuf), 0);if (-1 == ret){perror("Receive");exit(1);}printf("Receive : %s\n", RecvBuf.buf);memset(&RecvBuf, 0, sizeof(RecvBuf));}
}int main()
{int sockfd, ret;char buf[100] = {0};struct sockaddr_in server_addr; //向server_addr发起连接sockfd = socket(PF_INET, SOCK_STREAM, 0);   //创建socket,既用于连接,又用于发送信息if(-1 == sockfd){perror("socket");exit(1);}memset(&server_addr, 0, sizeof(server_addr));   //都是服务器信息server_addr.sin_family = PF_INET;server_addr.sin_port = PORT;server_addr.sin_addr.s_addr = inet_addr("192.168.192.128");printf("Start Connecting...\n");ret = connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));    //发起连接if (-1 == ret){perror("connect");exit(1);}ret = pthread_create(&tid[0], NULL, Send, (void *)&sockfd);     //创建线程,用于发送if (0 != ret){perror("pthread_creat1");exit(1);}ret = pthread_create(&tid[1], NULL, Receive, (void *)&sockfd);  //创建线程,用于接收if (0 != ret){perror("pthread_creat2");exit(1);}pthread_join(tid[0], NULL); //阻塞,不让线程结束pthread_join(tid[1], NULL);close(sockfd);return 0;
}

该程序还有些地方存在不足:
1.若一个客户端向另一个已经下线的客户端发送消息会出现混乱;
2.客户端之间发送消息时,消息内容不能还有含有空格,因为scanf输入消息内容和指定接收消息对象时是以空格为分界;
3.若客户端尚未关闭,直接关闭服务器会发生混乱(不过这点好像并不算不足吧,毕竟实际上服务器是长期开着的)

还有其他地方的不足 欢迎指出!

还有一点需要改进的地方:接收消息的一方不知道发送该消息的客户机(还请高手指教)

模拟QQ聊天——采用TCP协议的C/S架构实现相关推荐

  1. QQ使用了什么通讯协议?为什么要这样做?为什么采用 UDP 协议,而不采用 TCP 协议实现?

    登陆采用TCP协议和HTTP协议,你和好友之间发送消息,主要采用UDP协议,内网传文件采用了P2P技术. QQ对于普通用户是采用UDP协议,对于会员用TCP协议 总来的说: 1.登陆过程,客户端cli ...

  2. 初学java之模拟QQ聊天软件(简单实现)

    引言:这个程序是自从学习java以来写的第一个比较大的图形界面程序,花费了大约一周的时间,作为期末的课程设计,也算是基本上完成了任务,当然由于作者的编程能力有限,代码中难免存在BUG,不太简练,今天搬 ...

  3. Socket编程 ------ 模拟QQ聊天工具

    模拟QQ聊天 一.要求 1.一个服务器可以与多个用户同时通讯 2.用户可以通过服务器与用户之间通讯 3.用户可以选择和所有人发消息,也可以选择和某个用户单独发消息 4.服务器要显示当前所有在线人员 5 ...

  4. QQ为何采用UDP协议?

    https://blog.csdn.net/liusandian/article/details/52238939 登陆采用TCP协议和HTTP协议, 你和好友之间发送消息,主要采用UDP协议, 内网 ...

  5. 模拟QQ聊天小项目收尾---界面展示服务端与客户端进行信息交互(用到的知识:io,线程,Swing界面,面向对象思想...... )

    大家好,我是一位在java学习圈中不愿意透露姓名并苟且偷生的小学员,如果文章有错误之处,还望海涵,欢迎多多指正 如果你从本文学到有用的干货知识,那么请您尽量点赞,关注,评论,收藏 这两天我一直在设计这 ...

  6. python软件代码示例-用Python写一个模拟qq聊天小程序的代码实例

    Python 超简单的聊天程序 客户端: import socket, sys host = '10.248.27.23' # host = raw_input("Plz imput des ...

  7. 用python做毕业设计小程序_用Python写一个模拟qq聊天小程序的代码实例

    Python 超简单的聊天程序 客户端: import socket, sys host = '10.248.27.23' # host = raw_input("Plz imput des ...

  8. 能不能用python开发qq_用Python写一个模拟qq聊天小程序的代码实例

    用Python写一个模拟qq聊天小程序的代码实例 发布时间:2020-09-09 07:49:29

  9. 如何利用python实现qq聊天_用Python写一个模拟qq聊天小程序的代码实例

    Python 超简单的聊天程序 客户端: import socket, sys host = '10.248.27.23' # host = raw_input("Plz imput des ...

最新文章

  1. 输入带空格字符串的两种方法
  2. netty 管道和handler的加载和处理流程
  3. Elasticsearch和MongoDB对比
  4. tp框架存在的问题 不可多图同时上传
  5. Html跨页面调用函数,一个cshtml如何在另一个cshtml中调用一个函数?
  6. .NET 面向对象基础
  7. 使用Decimal.js解决前端计算金钱失真问题
  8. 4.Linux性能诊断 --- Linux工作流程内存管理
  9. 无头浏览器 html5定位,PhantomJS-无头浏览器的妙用
  10. Ubuntu安装wps,切换中文版,以及解决无法输入汉字的问题
  11. 小程序apkg还原_如何禁用微信小程序(适合任何机型的完美解决方案)
  12. 51中断编程c语言,有关51单片机中断的形式和C语言编程格式[精选5篇]
  13. SQL数据库连接失败
  14. 在线编译linux,在线就能用的Linux我给你找好了
  15. Spring MVC -- xxx conflicts with existing xxx
  16. 命令行中运行jar包(cmd)
  17. grpc、https、oauth2等认证专栏实战17:grpc-go自定义认证之base64验证介绍
  18. photoshop插画插件_一键生成2.5D风格插画的PS插件
  19. 看雪2W课-Frida逆向与利用自动化 Frida开发和调试环境搭建 课时1
  20. XiaoHu日志 9/7~9/17

热门文章

  1. AM335x添加WiFi模块WILC1000
  2. 10个设计最经典的web2.0网站
  3. 新海诚画集[秒速5センチメートル:樱花抄·遠野家]...
  4. [论文阅读笔记05]Deep Active Learning for Named Entity Recognition
  5. java php 架构_php 架构和java架构的区别?
  6. 广东培正计算机科学与技术,广东培正学院数据科学与计算机学院
  7. ipad手写笔哪款好?性价比高的触控笔
  8. 长春小学数学补习学校得花多少钱?
  9. 关于.netFramework概述
  10. 3ds MAX 灯光