当前位置: 首页 > 编程日记 > 正文

【Chat】实验 -- 实现 C/C++下TCP, 服务器/客户端 多人聊天室

本次实验利用TCP/IP, 语言环境为 C/C++

利用套接字Socket编程,以及线程处理,

实现Server/CLient 之间多人的聊天系统的基本功能。

结果大致如:

下面贴上代码(参考参考...)

Server 部分:

  1 /* TCPdtd.cpp - main, TCPdaytimed */
  2 
  3 #include <stdlib.h>
  4 #include <stdio.h>
  5 #include <winsock2.h>
  6 #include <time.h>
  7 #include "conio.h"
  8 #include <windows.h>
  9 #include <process.h>
 10 #include <math.h>
 11 
 12 #define QLEN       5
 13 #define    WSVERS    MAKEWORD(2, 0)
 14 #define    BUFLEN    2000             // 缓冲区大小
 15 #pragma comment(lib,"ws2_32.lib")  //winsock 2.2 library
 16 
 17     SOCKET    msock, ssock;            /* master & slave sockets           */
 18     SOCKET    sockets[100] = {NULL};
 19      
 20      int cc;
 21      char    *pts;                    /* pointer to time string           */
 22      time_t    now;                    /* current time                       */
 23      char buf[2000];                      /* buffer                          */
 24      char *input;
 25      HANDLE hThread1,hThread[100] = {NULL};
 26     unsigned int threadID,ThreadID[100],number;
 27 
 28     struct    sockaddr_in fsin;
 29     struct    sockaddr_in Sin;
 30 
 31 unsigned int __stdcall Chat(PVOID PM) 
 32 {    
 33         char buf1[2000];
 34         char buf2[2000];
 35         char buf3[2000];
 36         char buf4[2000];
 37         (void) time(&now);
 38         pts = ctime(&now);
 39         sockets[number] = ssock;
 40         SOCKET    sock = ssock;
 41         ThreadID[number] = threadID;
 42         unsigned int threadid = threadID;
 43         sprintf(buf1," 时间: %s  \t【我的线程号: %d 】\n",pts,threadid);
 44         (void) send(sock,buf1, sizeof(buf1), 0); 
 45         sprintf(buf2," 线程号 <%d> 客户<IP:%s 端口:%d>  enter  \n",threadid,inet_ntoa(fsin.sin_addr),fsin.sin_port);
 46         printf("%s ",buf2);        
 47         printf("\t将自动把此数据发送给所有客户! \n");
 48         for(int i=0;i<=number;i++)
 49         {            
 50             if(sockets[i] != NULL && sockets[i] != sock)
 51             {
 52             (void) send(sockets[i],buf2, sizeof(buf2), 0); 
 53             printf(" 发送至线程号<%d>成功!\n",ThreadID[i]);
 54             }
 55         }
 56         printf(" \n");
 57 
 58 
 59 flag1:cc = recv(sock, buf3, BUFLEN, 0);   //cc为接收的字符数
 60     if(cc == SOCKET_ERROR|| cc == 0)
 61     {
 62         (void) time(&now);
 63         pts = ctime(&now);
 64         sprintf( buf3," 线程号 <%d> 客户<IP:%s 端口:%d>  leave !  \n \t\t时间: %s",threadid,inet_ntoa(fsin.sin_addr),fsin.sin_port,pts);
 65         sock = NULL;    
 66         sockets[number] = NULL;
 67         CloseHandle(hThread[number]);
 68         printf("%s ", buf3);        
 69         printf("\t将自动把此数据发送给所有客户! \n");
 70         for(int i=0;i<=number;i++)
 71         {            
 72             if(sockets[i] != NULL && sockets[i] != sock)
 73             {
 74             (void) send(sockets[i], buf3, sizeof(buf3), 0);     
 75             printf(" 发送至线程号<%d>成功!\n",ThreadID[i]);
 76             }            
 77         }
 78     printf(" \n");
 79     }
 80 
 81     else if(cc > 0) 
 82     {
 83         (void) time(&now);
 84         pts = ctime(&now);
 85     sprintf(buf4," 线程号 <%d> 客户<IP:%s 端口:%d>说 :%s  \n \t\t时间 : %s",threadid,inet_ntoa(fsin.sin_addr),fsin.sin_port,buf3,pts);
 86     
 87         printf("%s ",buf4);
 88         printf("\t将自动把此数据发送给所有客户! \n");
 89         for(int i=0;i<=number;i++)
 90         {            
 91             if(sockets[i] != NULL && sockets[i] != sock)
 92             {
 93             (void) send(sockets[i],buf4, sizeof(buf4), 0);         
 94             printf(" 发送至线程号<%d>成功!\n",ThreadID[i]);
 95             }            
 96         }
 97         printf(" \n");
 98 
 99         goto flag1;
100     }
101         (void) closesocket(sock);
102     
103         return 0;
104         }
105 
106 
107 /*------------------------------------------------------------------------
108  * main - Iterative TCP server for DAYTIME service
109  *------------------------------------------------------------------------
110  */
111 void main(int argc, char *argv[]) 
112 /* argc: 命令行参数个数, 例如:C:\> TCPdaytimed 8080 
113                      argc=2 argv[0]="TCPdaytimed",argv[1]="8080" */
114 {
115     int     alen;                    /* from-address length               */    
116     WSADATA wsadata; 
117     char    *service = "5050";    
118     WSAStartup(WSVERS, &wsadata);                         //加载 winsock 2.2 library
119     msock = socket(PF_INET, SOCK_STREAM, 0);              //生成套接字。TCP协议号=6, UDP协议号=17
120     memset(&Sin, 0, sizeof(Sin));
121     Sin.sin_family = AF_INET;
122     Sin.sin_addr.s_addr = INADDR_ANY;                    //指定绑定接口的IP地址。INADDR_ANY表示绑定(监听)所有的接口。
123     Sin.sin_port = htons((u_short)atoi(service));        //atoi--把ascii转化为int,htons - 主机序(host)转化为网络序(network), s(short) 
124     bind(msock, (struct sockaddr *)&Sin, sizeof(Sin));   // 绑定端口号(和IP地址)
125     listen(msock, 5);                                    //队列长度为5
126 
127     printf("\t\t\t\t Chat 多人聊天程序 \n");
128     printf("\t\t\t\t       (Server) \n");
129      (void) time(&now);
130       pts = ctime(&now);
131     printf("\t\t\t  时间 :%s",pts);
132         number = -1;
133     while(1)                                    //检测是否有按键
134     {                
135         alen = sizeof(struct sockaddr);
136         ssock = accept(msock, (struct sockaddr *)&fsin, &alen);
137         number ++;
138         hThread[number] = (HANDLE)_beginthreadex(NULL, 0,Chat,NULL, 0, &threadID);        
139     }
140     (void) closesocket(msock);
141     WSACleanup();                         //卸载载 winsock 2.2 library
142 }
View Code

Client 部分:

  1 /* TCPClient.cpp  -- 用于传递struct */
  2 #include <stdlib.h>
  3 #include <stdio.h>
  4 #include <winsock2.h>
  5 #include <string.h>
  6 #include <time.h>
  7 #include <windows.h>
  8 #include <process.h>
  9 #include <math.h>
 10 
 11 #define    BUFLEN        2000                  // 缓冲区大小
 12 #define WSVERS        MAKEWORD(2, 0)        // 指明版本2.0 
 13 #pragma comment(lib,"ws2_32.lib")         // 指明winsock 2.0 Llibrary
 14 
 15 /*------------------------------------------------------------------------
 16  * main - TCP client for DAYTIME service
 17  *------------------------------------------------------------------------
 18  */
 19     
 20     SOCKET    sock,sockets[100] = {NULL};                          /* socket descriptor            */
 21 //    int    cc;                                /* recv character count            */
 22     char    *packet = NULL;               /* buffer for one line of text    */
 23     char *pts,*input;
 24     HANDLE hThread;
 25     unsigned threadID;
 26 
 27 unsigned int __stdcall Chat(PVOID PM ) 
 28 {
 29        time_t    now;
 30       (void) time(&now);
 31        pts = ctime(&now);
 32        char buf[2000];
 33 
 34 while(1)
 35 {
 36     int cc = recv(sock, buf, BUFLEN, 0);   //cc为接收的字符数
 37     if(cc == SOCKET_ERROR|| cc == 0)
 38     {
 39         printf("Error: %d.----",GetLastError());
 40         printf("与服务器断开连接!\n");
 41         CloseHandle(hThread);
 42         (void)closesocket(sock);
 43         break;
 44     }
 45     else if(cc > 0) 
 46     {
 47     //    buf[cc] = '\0';
 48         printf("%s\n",buf);
 49     //    printf("输入数据(exit退出):  \n");
 50     }     
 51 }
 52     return 0;
 53 }
 54 
 55 int main(int argc, char *argv[])
 56 {
 57     time_t    now;
 58      (void) time(&now);
 59        pts = ctime(&now);
 60     char    *host = "127.0.0.1";        /* server IP to connect         */
 61 //    char    *host = "172.18.33.155";
 62 //    char    *host = "172.18.33.93";
 63 //    char    *host = "172.18.187.1";
 64     char *service = "5050";          /* server port to connect       */
 65 //    char *service = "50000";
 66     struct  sockaddr_in sin;            /* an Internet endpoint address    */
 67     WSADATA wsadata;
 68     WSAStartup(WSVERS, &wsadata);       /* 启动某版本Socket的DLL        */        
 69 
 70     memset(&sin, 0, sizeof(sin));
 71     sin.sin_family = AF_INET;
 72     sin.sin_port = htons((u_short)atoi(service));    //atoi:把ascii转化为int. htons:主机序(host)转化为网络序(network), s--short
 73     sin.sin_addr.s_addr = inet_addr(host);           //如果host为域名,需要先用函数gethostbyname把域名转化为IP地址
 74 
 75     sock = socket(PF_INET, SOCK_STREAM,0);
 76 
 77     connect(sock, (struct sockaddr *)&sin, sizeof(sin));
 78 
 79     printf("\t\t\t\tChat 多人聊天程序 \n");
 80     printf("\t\t\t\t       (Client) \n");
 81     hThread = (HANDLE)_beginthreadex(NULL, 0,Chat, NULL, 0, &threadID);    
 82     printf(" \t\t\t\t 【您可以自由发言】\n\n");
 83 while(1)
 84 {
 85     char buf1[2000];
 86     
 87     //     scanf("%s",&buf1);
 88     
 89          gets_s(buf1);
 90          if(!strcmp(buf1 ,"exit"))
 91              goto end;
 92 
 93         (void) send(sock,buf1, sizeof(buf1), 0);
 94         (void) time(&now);
 95         pts = ctime(&now);
 96        printf(" 发送成功! ------时间: %s\n",pts);
 97 }
 98     
 99 end:    CloseHandle(hThread);
100         closesocket(sock);
101         WSACleanup();                     /* 卸载某版本的DLL */  
102 
103     printf("按回车键继续...");
104     getchar();
105     return 0;                           /* exit */
106 }
View Code

相关文章:

TeamViewer介绍:远程控制计算机

TeamViewer是一个可以远程控制计算机的程序&#xff0c;它也可以进行远程文件传输。TeamViewer支持的平台比较多&#xff0c;如Windows, Mac, Linux, ChromeOs, Android, iOS等&#xff0c;最新发布版本为14.x&#xff0c;它有个人免费和商业付费两种。只要对方告诉你他的TeamV…

PyTorch攻势凶猛,程序员正在抛弃TensorFlow?

来源 | The Gradient译者 | 夕颜出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;自 2012 年深度学习重新获得重视以来&#xff0c;许多机器学习框架便争相成为研究人员和行业从业人员的新宠。从早期的学术成果 Caffe 和 Theano &#xff0c;到背靠庞大工业支持的 PyT…

swift 错误集合 ------持续更新中

从今天开始凡是在用swift中遇到的错误都会在本博客持续更新 便于自己学习和快速开发 2017.7.20 如果你的程序写的有进入后台的方法&#xff0c;例如我的博客中点击home进入后台持续定位的那篇文章&#xff0c;发信进入后台后定位没有按得定时器规定的时间走&#xff0c;这…

【转载】【贪心】各种覆盖问题

1、独立区间问题 在N个区间里找出最多的互不覆盖的区间 对结束点进行排序&#xff0c;然后从结束点最小的区间开始进行选择即可 2、覆盖区间问题 给一个大区间&#xff0c;再给出N个小区间&#xff0c;求出最少用多少个区间可以把大区间覆盖完 先选出开始的一个&#xff0c;然后…

使用Python3发送邮件测试代码

SMTP(Simple Mail Trasfer Protocol)即简单邮件传输协议&#xff0c;它是一组用于由源地址到目的地址传送邮件的规则&#xff0c;用它来控制信件的中转方式。Python3对SMTP的支持有smtplib和email两个模块&#xff0c;smtplib负责发送电子邮件&#xff0c; email负责组织邮件内…

swift 通知中心 进入后台多久会通知用户关闭此功能

//添加本地通知 func addLocalNotification() { //定义本地通知对象 let notification : UILocalNotification UILocalNotification() //设置调用时间 notification.fireDate NSDate.init(timeIntervalSinceNow: 1800.0)//通知触发的时间&#xff0c;10s以后 notification.…

Python之父退休,C语言之父与世长辞,各大编程语言创始人现状盘点

作者 | 年素清 编辑 | 伍杏玲 来源 | 程序人生&#xff08;ID&#xff1a;coder_life&#xff09;从世界上第一台计算机(ENIAC) 于1946年2月在美国诞生至今的七十多年里&#xff0c;涌现出了许多优秀的计算机编程语言。程序员们在使用它们编写程序的时候&#xff0c;一定很好奇…

linux修正系统错误指令fsck和badblocks

fsck [-t文件系统][-ACay]装置名称-t 指定文件系统-A 扫描需要的装置-a 自动修复检查到有问题的扇区-y 与-a类似-C 在检查过程中&#xff0c;显示进度********************************************************** EXT2/EXT3额外选项功能&#xff1a;-f 强制检查-D 针对文件系…

Ubuntu定时任务crontab命令介绍

通过Linux上的crontab命令&#xff0c;我们可以在规定的间隔时间执行指定的系统指令或脚本。时间间隔的单位可以是分钟、小时、日、月、周及以上的任意组合。 crontab默认在Ubuntu上是已经安装的&#xff0c;若未安装&#xff0c;则可执行以下命令进行安装&#xff1a; sudo …

swift 进入后台或者点击home键是程序进入后台后,持续定位

进入后台的方法 import UIKit UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate,CLLocationManagerDelegate { var locationManager : CLLocationManager? var window: UIWindow? var notificationDict NSDictionary() func applicationDidEnterBa…

求助:我有一辆机器人小车,怎么让它跑起来,还会避障、目标跟踪、路径规划?...

也许&#xff0c;你曾见过能灵活地绕开障碍物的它在桌子边缘“疯狂试探”的它它是谁&#xff1f;没错&#xff0c;它就是是英伟达推出的一款入门级人工智能小车——Jetbot &#xff0c;估计对机器人&#xff0c;尤其是对车械感兴趣的朋友们一定对它不陌生。组装完成后能够通过摄…

Python-常用字符串转换实例

当字符串是&#xff1a;\u4e2d\u56fd >>>s[\u4e2d\u56fd,\u6e05\u534e\u5927\u5b66]>>>strs[0].decode(unicode_escape) #.encode("EUC_KR")>>>print str 中国 当字符串是: >>>print unichr(19996) 东 ord()支持unicode&…

什么是静态UItableView

iOS开发UI篇—简单介绍静态单元格的使用 iOS开发UI篇—简单介绍静态单元格的使用 一、实现效果与说明 说明&#xff1a;观察上面的展示效果&#xff0c;可以发现整个界面是由一个tableview来展示的&#xff0c;上面的数据都是固定的&#xff0c;且几乎不会改变。 要完成上面的…

Python3中PyMongo使用举例

MongoDB是一个基于分布式文件存储的开源数据库&#xff0c;由C语言编写&#xff0c;与平台无关&#xff0c;旨在为WEB应用提供可扩展的高性能数据存储解决方案。MongoDB是一个介于关系数据库和非关系数据库之间的产品&#xff0c;是非关系数据库中功能最丰富&#xff0c;最像关…

PyTorch踩过的12坑 | CSDN博文精选

作者 | hyk_1996 来源 | CSDN博客1. nn.Module.cuda() 和 Tensor.cuda() 的作用效果差异无论是对于模型还是数据&#xff0c;cuda()函数都能实现从CPU到GPU的内存迁移&#xff0c;但是他们的作用效果有所不同。对于nn.Module:model model.cuda() model.cuda() 上面两句能够达到…

解决ubuntu14.04下Qt 5.3.1下的QtCreator fcitx,ibus不能输入中文

2019独角兽企业重金招聘Python工程师标准>>> ubuntu 14.04从Qt官网下载的最新版qt&#xff0c;安装过程很顺利&#xff0c;但却发现没办法输入中文&#xff08;我用的是 fcitx), 即使下载了fcitx-frontend-qt5和fcitx-frontend-qt4也还是没用。 想必是qt版本的原因吧…

实战:基于技术分析的Python算法交易

译者 | Tianyu 出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;本文是用 Python 做交易策略回测系列文章的第四篇。上个部分介绍了以下几个方面内容&#xff1a;介绍了 zipline 回测框架&#xff0c;并展示了如何回测基本的策略导入自定义的数据并使用 zipline评估交…

深度学习中的Dropout简介及实现

在训练神经网络模型时候&#xff0c;如果模型相对复杂即参数较多而训练样本相对较少&#xff0c;这时候训练出的模型可能对训练集中的数据拟合的比较好&#xff0c;但在测试集上的表现较差&#xff0c;即出现了过拟合的情况。这种情况下可以使用Dropout来降低过拟合的可能性进而…

swift中字符串截取方法(substring)

下面介绍2种swift的字符串截取方法,实际上用到了substringFromIndex,substringToIndex,substringWithRange 1.将String转化为NSString再截取,代码如下&#xff1a; var s"1234567890"var ns1(s as NSString).substringFromIndex(5) var ns2(s as NSString).substrin…

设置IE兼容模式

文件兼容性用于定义让IE如何编译你的网页。此文件解释文件兼容性&#xff0c;如何指定你网站的文件兼容性模式以及如何判断一个网页该使用的文件模式。 前言 为了帮助确保你的网页在所有未来的IE版本都有一致的外观&#xff0c;IE8引入了文件兼容性。在IE6中引入一个增设的兼容…

程序员的自我修养--链接、装载与库笔记:静态链接

1. 空间与地址分配 对于链接器来说,整个链接过程中,它就是将几个输入目标文件加工后合并成一个输出文件。测试代码a.c和b.c内容如下&#xff1a; // a.c extern int shared;int main() {int a 100;swap(&a, &shared); } // b.c int shared 1;void swap(int* a, in…

开启JAVA自学新篇章

MyEclipse Enterprise Workbench简称MyEclipse&#xff0c;是一款专门用于开发Java, J2EE的 Eclipse 插件集合&#xff0c;该软件不仅功能丰富而且强大&#xff0c;包括了完备的编码、调试、测试和发布功能&#xff0c;利用它我们可以在数据库和JavaEE的开发、发布以及应用程序…

12306系统的秒杀“艺术”:如何抗住100万人同时抢1万张票?

作者 | IT牧场 编辑 | 阿秃每到节假日期间&#xff0c;一二线城市返乡、外出游玩的人们几乎都面临着一个问题——抢火车票。虽然现在大多数情况下都能订到票&#xff0c;但是放票瞬间即无票的场景&#xff0c;相信大家都深有体会。尤其是春节期间&#xff0c;大家不仅使用 1230…

C#不错的扩展工具类

FSLibExtension.NET https://github.com/iccfish/FSLib.Extension WebEssentials2013 https://github.com/iccfish/WebEssentials2013

自己写的程序密码功能 ------数字功能

自己写的程序密码功能 ------数字功能 class LockedViewController: UIViewController { var dataBase:FMDatabase? var i 0 var passwordStr : String? var tempStr : String "" var numStr : String "" //初始输入密码 var reNumStr : String &…

程序员的自我修养--链接、装载与库笔记:Windows PE/COFF

1. Windows的二进制文件格式PE/COFF 在32位Windows平台下&#xff0c;微软引入了一种叫PE(Portable Executable)的可执行格式。作为Win32平台的标准可执行文件格式&#xff0c;PE有着跟ELF一样良好的平台扩展性和灵活性。PE文件格式事实上与ELF同根同源&#xff0c;它们都是由…

神州数码与神州控股、神州信息共同主办首届技术年会,透露出什么信号?

11 月 8 日&#xff0c;神州控股、神州数码集团、神州信息共同主办“数字中国 2019 技术年会”&#xff0c;聚焦云计算、大数据、人工智能、区块链、5G 等前沿技术创新与应用实践&#xff0c;众多领域的技术专家展开了深度交流&#xff0c;共同探讨数字时代的技术创新与协同发展…

osi七层协议和tcp/ip四层协议

&#xff08;大部分内容为转载&#xff09;OSI&#xff08;Open System Interconnection&#xff09;是一个开放性的通行系统互连参考模型&#xff0c;他是一个定义的非常好的协议规范&#xff0c;共包含七层协议。OSI七层协议是由ISO (International Standards Organization)在…

Swift中页面跳转与传值:

1.简单方式 首先&#xff0c;Swift的跳转可分为利用xib文件跳转与storyboard跳转两种方法&#xff0c;我这里选择使用storyboard的界面跳转方法。 1、通过在storyboard中拉button控件建立segue跳转。 2、通过presentViewController方法进行界面跳转。 这里需要注意presentV…

知乎热议!学完Python之后,我的编程能力竟然退化了!

在知乎上有一个特别火的问题&#xff1a;如何学Python&#xff1f;你会看到很多高赞回答是&#xff1a;我一天就学完了。在大家群嘲的背后&#xff0c;我们来分析一下&#xff0c;为什么在已经学过的人眼里&#xff0c;Python这么容易学&#xff0c;甚至简单到被某些人鄙视呢&a…