一、协议设计

使用流套接字(SOCK_STREAM),流套接字用于面向连接,可靠的数据传输服务。它使用了传输控制协议TCP。在聊天的程序中需要一个服务器一个客户端。
在会话进行的流程中,服务器端先创建套接字(socket())再将其与ip地址和端口绑定(bind()),然后开始监听listen(),再使用accept()阻塞进程直到有客户端连接。客户端创建套接字socket(),再使用connect()建立连接客户端,wirte()请求数据,然后服务器read()接收请求,服务器处理请求之后write()回应数据,客户端用read()接收数据如果数据中没有退出信息,则再回到请求数据的步骤。若有退出指令则客户端退出close()关闭连接然后服务器read()后close()或者服务器先close()关闭连接然后客户端read()后close()。
流程如下图所示:

在通话开始前,用户端和服务器交换彼此的名字开始通话,由客户端先开始发言,完毕后输入over服务器才能发消息回客户端。之后客户端也是在服务器端输入over才能发言。双方任意一方均可输入“exit“来结束对话退出程序。

二、代码实现

//server.cpp
1.  #include<iostream>
2.  #include<winsock.h>
3.  #include<string.h>
4.  #pragma comment(lib, "ws2_32.lib")
5.  //加载ws2_32.lib库
6.  using namespace std;
7.  int main() {
8.
9.      WSADATA wsaData; //存放被WSAStartup函数调用后返回的Windows Sockets数据的数据结构
10.     WSAStartup(MAKEWORD(2, 2), &wsaData);//声明使用socket2.2版本
11.     //创建套接字
12.     SOCKET ServerSocket;
13.     //地址类型为AD_INET,服务类型为流式(SOCK_STREAM),协议采用TCP
14.     ServerSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
15.     if (ServerSocket == INVALID_SOCKET)
16.     {
17.         cout << "套接字创建失败";
18.         WSACleanup();
19.         return 0;
20.     }
21.
22.     SOCKADDR_IN ServerAddr;
23.     ServerAddr.sin_family = AF_INET;     //指定IP格式
24.     USHORT uPort = 8888;                 //服务器监听端口
25.     ServerAddr.sin_port = htons(uPort);   //绑定端口号
26.     ServerAddr.sin_addr.S_un.S_addr = INADDR_ANY;
27.     if (bind(ServerSocket, (SOCKADDR*)&ServerAddr, sizeof(ServerAddr)) == SOCKET_ERROR)  //建立捆绑
28.     {
29.         cout << "绑定失败";
30.         closesocket(ServerSocket);
31.         return 0;
32.     }
33.     char server_name[32] = { 0 };
34.     cout << "请输入你的名字:";
35.     cin.getline(server_name,32);
36.
37.     /*开始监听*/
38.     listen(ServerSocket, 1);
39.
40.     /*等待连接*/
41.     char client_name[32] = { 0 };
42.     SOCKET ClientSocket;
43.     SOCKADDR_IN ClientAddr;
44.     int ClientAddrlen = sizeof(ClientAddr);
45.     ClientSocket = accept(ServerSocket,(SOCKADDR*)&ClientAddr,&ClientAddrlen);
46.     cout << "等待连接...\n";
47.     if (ClientSocket == INVALID_SOCKET)
48.     {
49.         cout << "客户端发出请求,服务器接收请求失败:\n" << WSAGetLastError();
50.         closesocket(ServerSocket);
51.         WSACleanup();
52.         return 0;
53.     }
54.     else
55.     {
56.         cout << "客服端与服务器建立连接成功:\n" ;
57.     }
58.     char buffer[1024] = { 0 };
59.     int relen = 0;
60.     int selen = 0;
61.     /*通过建立的连接进行通信*/
62.     //发送和接受客户端与服务端的名字
63.     selen=send(ClientSocket, server_name, strlen(server_name), 0);
64.     relen=recv(ClientSocket, client_name, sizeof(client_name), 0);
65.     client_name[relen] = '\0';
66.     while (1)
67.     {
68.         while (1)
69.         {
70.             memset(buffer, 0, sizeof(buffer));//在每次交互前,把之前的buf数据清空,避免缓冲区冗余
71.             relen = recv(ClientSocket, buffer, sizeof(buffer), 0);
72.             /*buffer[relen] = '\0';*/
73.             //接受消息
74.             if (strcmp(buffer, "exit") == 0)//输入消息含有exit便退出
75.             {
76.                 cout << "程序将在3秒后退出" << endl;
77.                 Sleep(3000);
78.                 closesocket(ServerSocket);
79.                 closesocket(ClientSocket);
80.                 WSACleanup();
81.                 return 0;
82.             }
83.             else if (strcmp(buffer, "over") == 0)
84.             {
85.                 break;
86.             }
87.             cout << client_name << ": ";
88.             cout << buffer << endl;
89.         }
90.         while (1) {
91.             memset(buffer, 0, sizeof(buffer));
92.             cout << server_name << ": ";
93.             cin.getline(buffer,1024);
94.             //发出消息
95.             if (strcmp(buffer, "over") == 0)
96.             {
97.                 selen = send(ClientSocket, buffer, sizeof(buffer), 0);
98.                 break;
99.             }
100.                else if(strcmp(buffer, "exit") == 0)
101.                {
102.                    selen = send(ClientSocket, buffer, sizeof(buffer), 0);
103.                    cout << "程序将在3秒后退出" << endl;
104.                    Sleep(3000);
105.                    closesocket(ServerSocket);
106.                    closesocket(ClientSocket);
107.                    WSACleanup();
108.                    return 0;
109.                }
110.                selen = send(ClientSocket, buffer, sizeof(buffer), 0);
111.            }
112.        }
113.    }

客户端

\\client.cpp
114.    #include<iostream>
115.    #include<winsock.h>
116.    #include<string.h>
117.    #pragma comment(lib, "ws2_32.lib")
118.    //加载ws2_32.lib库
119.    using namespace std;
120.    int main() {
121.
122.        WSADATA wsaData; //存放被WSAStartup函数调用后返回的Windows Sockets数据的数据结构
123.        WSAStartup(MAKEWORD(2, 2), &wsaData);//声明使用socket2.2版本
124.        //创建套接字
125.        SOCKET ClientSocket;
126.        //地址类型为AD_INET,服务类型为流式(SOCK_STREAM),协议采用TCP
127.        ClientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
128.        if (ClientSocket == INVALID_SOCKET)
129.        {
130.            cout << "套接字创建失败";
131.            WSACleanup();
132.            return 0;
133.        }
134.
135.        SOCKADDR_IN ServerAddr;
136.        ServerAddr.sin_family = AF_INET;     //指定IP格式
137.        USHORT uPort = 8888;                 //服务器监听端口
138.        ServerAddr.sin_port = htons(uPort);   //绑定端口号
139.        ServerAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
140.        char client_name[32] = { 0 };
141.        cout << "请输入你的名字:";
142.        cin.getline( client_name,32);
143.        connect(ClientSocket, (SOCKADDR*)&ServerAddr, sizeof(ServerAddr));
144.        cout << "连接成功" << endl;
145.
146.        /*等待连接*/
147.        char server_name[32] = { 0 };
148.        char buffer[1024] = { 0 };
149.        int relen = 0;
150.        int selen = 0;
151.        /*通过建立的连接进行通信*/
152.        //发送和接受客户端与服务端的名字
153.        selen = send(ClientSocket, client_name, strlen(client_name), 0);
154.        relen = recv(ClientSocket, server_name, sizeof(server_name), 0);
155.        /*server_name[relen] = '\0';*/
156.        while (1)
157.        {
158.            while (1) {
159.                cout << client_name << ": ";
160.                memset(buffer, 0, sizeof(buffer));
161.                cin.getline(buffer,sizeof(buffer));
162.                if (strcmp(buffer, "exit") == 0)
163.                {
164.                    selen = send(ClientSocket, buffer, sizeof(buffer), 0);
165.                    cout << "程序将在3秒后退出" << endl;
166.                    Sleep(3000);
167.                    closesocket(ClientSocket);
168.                    WSACleanup();
169.                    return 0;
170.                }
171.                else if (strcmp(buffer, "over") == 0)
172.                {
173.                    selen = send(ClientSocket, buffer, sizeof(buffer), 0);
174.                    break;
175.                }
176.                selen = send(ClientSocket, buffer, sizeof(buffer), 0);
177.            }
178.            while (1) {
179.                memset(buffer, 0, sizeof(buffer));//在每次交互前,把之前的buf数据清空,避免缓冲区冗余
180.                relen = recv(ClientSocket, buffer, sizeof(buffer), 0);
181.                //buffer[relen] = '\0';//接受消息
182.                if (strcmp(buffer, "exit") == 0)//输入消息含有exit便退出
183.                {
184.                    cout << buffer <<"程序将在3秒后退出" <<endl;
185.                    Sleep(3000);
186.                    closesocket(ClientSocket);
187.                    WSACleanup();
188.                    return 0;
189.                }
190.                else if (strcmp(buffer, "over") == 0)
191.                {
192.                    break;
193.                }
194.                cout << server_name << ": ";
195.                cout << buffer << endl;
196.            }
197.        }
198.    }
199

三、 实验结果

c++socket双人聊天相关推荐

  1. Socket通信,实现简单的双人聊天功能

    Socket通信 1.简单介绍 学习Socket也只是通过一个小例子学习的,关于Socket原理目前只是了解到是基于TCP协议,关于TCP与UDP协议区别可以去百度详情查一下他们的区别之处,大体上是传 ...

  2. Java--网络编程(利用UDP实现简单的双人聊天)

    1 UDP的定义 UDP(User Datagram Protocol)是一个无连接的传输层协议,提供了无连接通信,且不对传送数据包进行可靠性保证,适合于一次传输少量数据.UDP报文没有可靠性保证.顺 ...

  3. C# Socket实现聊天通信

    C# Socket实现聊天通信 下面这个实例是一个完整的使用Socket实现的聊天(只限于局域网,如果能提供一个高权限的IP就可以实现类似QQ聊天),其中的原理是:首先开启服务端,打开侦听(任何端口为 ...

  4. 2Python全栈之路系列之基于socket实现聊天机器人

    Python全栈之路系列之基于socket实现聊天机器人 通过socket实现局域网内的聊天工具. service.py文件如下: #!/usr/bin/env python # _*_ coding ...

  5. 使用Socket模拟聊天室

    使用Socket模拟聊天室 文章目录 使用Socket模拟聊天室 客户端 客户端读线程 客户端写线程 客户主函数 服务端 服务端线程 服务端主函数 客户端 客户端读线程 public class Ec ...

  6. Socket.IO聊天室~简单实用

    小编心语:大家过完圣诞准备迎元旦吧~小编在这里预祝大家元旦快乐!!这一次要分享的东西小编也不是很懂啊,总之小编把它拿出来是觉地比较稀奇,而且程序也没有那么难,是一个比较简单的程序,大家可以多多试试~ ...

  7. java socket 工具_java Socket简易聊天工具

    本文实例为大家分享了一款Socket简易聊天工具,希望大家喜欢. 代码运行如图,看起来还不错 服务端 package qiu; import java.awt.BorderLayout; import ...

  8. Android 基于Socket的聊天室

    原文地址为: Android 基于Socket的聊天室 Socket是TCP/IP协议上的一种通信,在通信的两端各建立一个Socket,从而在通信的两端之间形成网络虚拟链路.一旦建立了虚拟的网络链路, ...

  9. socket局域网聊天demo

    socket局域网聊天demo,地址包内有实现源码:https://download.csdn.net/download/wyazyf/11457936

最新文章

  1. PHP 各种实用资源
  2. JAVA字符流与字符集编码
  3. 安装open3d python
  4. [转载]Qt之自定义界面(二)添加最小化、关闭按钮、添加背景_vortex_新浪博客...
  5. manifest.json文件的 “name” “description” “version 字段解释
  6. html5 mid格式音乐,html5中audio支持音频格式的解决方法
  7. yarn install命令运行报错:无法将“yarn”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。
  8. 电商分析公式和指标整理
  9. 学北邮计算机未来四十岁,2020年北京邮电大学计算机研究生保研心得
  10. 导向滤波算法原理与代码
  11. GAN的一些经典网络的基本思想
  12. [Lonlife1031]Bob and Alice are eating food(递推,矩阵快速幂)
  13. JS学习之路系列总结四象阵(此文犹如武林之中的易筋经,是你驰骋IT界的武功心法,学会JS五大阵法就学会了JS,博主建议先学三才阵)...
  14. uni-app学习 组件---a链接的跳转(四)
  15. 附录:入行 AI,选个脚踏实地的岗位
  16. 嵌入式Linux磁盘(硬盘、SD卡)读写性能测试
  17. chrome图片下载插件
  18. [LeetCode]Medium - Cutting Ribbons - python
  19. HTML5学习笔记(三)
  20. 课程设计每日总结0820

热门文章

  1. 微信小程序:录音功能(授权、统计时长、上传)
  2. 定义一个结构体变量(包括年、月、日)。计算该日在本年中是第几天?注意闰年问题。
  3. 光电效应的历史:爱因斯坦与莱纳德之间的争斗
  4. JavaScript进阶之路(一)初学者的开始
  5. Android显示GIF动画
  6. PTA 7-5 彩虹瓶
  7. MacBook Pro M1配置jdk
  8. 机器人运动逆解算IK
  9. (原码、反码和补码)例子byte的详细讲解
  10. Python-OpenCV中的图像处理 » 轮廓:入门