c++socket双人聊天
一、协议设计
使用流套接字(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双人聊天相关推荐
- Socket通信,实现简单的双人聊天功能
Socket通信 1.简单介绍 学习Socket也只是通过一个小例子学习的,关于Socket原理目前只是了解到是基于TCP协议,关于TCP与UDP协议区别可以去百度详情查一下他们的区别之处,大体上是传 ...
- Java--网络编程(利用UDP实现简单的双人聊天)
1 UDP的定义 UDP(User Datagram Protocol)是一个无连接的传输层协议,提供了无连接通信,且不对传送数据包进行可靠性保证,适合于一次传输少量数据.UDP报文没有可靠性保证.顺 ...
- C# Socket实现聊天通信
C# Socket实现聊天通信 下面这个实例是一个完整的使用Socket实现的聊天(只限于局域网,如果能提供一个高权限的IP就可以实现类似QQ聊天),其中的原理是:首先开启服务端,打开侦听(任何端口为 ...
- 2Python全栈之路系列之基于socket实现聊天机器人
Python全栈之路系列之基于socket实现聊天机器人 通过socket实现局域网内的聊天工具. service.py文件如下: #!/usr/bin/env python # _*_ coding ...
- 使用Socket模拟聊天室
使用Socket模拟聊天室 文章目录 使用Socket模拟聊天室 客户端 客户端读线程 客户端写线程 客户主函数 服务端 服务端线程 服务端主函数 客户端 客户端读线程 public class Ec ...
- Socket.IO聊天室~简单实用
小编心语:大家过完圣诞准备迎元旦吧~小编在这里预祝大家元旦快乐!!这一次要分享的东西小编也不是很懂啊,总之小编把它拿出来是觉地比较稀奇,而且程序也没有那么难,是一个比较简单的程序,大家可以多多试试~ ...
- java socket 工具_java Socket简易聊天工具
本文实例为大家分享了一款Socket简易聊天工具,希望大家喜欢. 代码运行如图,看起来还不错 服务端 package qiu; import java.awt.BorderLayout; import ...
- Android 基于Socket的聊天室
原文地址为: Android 基于Socket的聊天室 Socket是TCP/IP协议上的一种通信,在通信的两端各建立一个Socket,从而在通信的两端之间形成网络虚拟链路.一旦建立了虚拟的网络链路, ...
- socket局域网聊天demo
socket局域网聊天demo,地址包内有实现源码:https://download.csdn.net/download/wyazyf/11457936
最新文章
- PHP 各种实用资源
- JAVA字符流与字符集编码
- 安装open3d python
- [转载]Qt之自定义界面(二)添加最小化、关闭按钮、添加背景_vortex_新浪博客...
- manifest.json文件的 “name” “description” “version 字段解释
- html5 mid格式音乐,html5中audio支持音频格式的解决方法
- yarn install命令运行报错:无法将“yarn”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。
- 电商分析公式和指标整理
- 学北邮计算机未来四十岁,2020年北京邮电大学计算机研究生保研心得
- 导向滤波算法原理与代码
- GAN的一些经典网络的基本思想
- [Lonlife1031]Bob and Alice are eating food(递推,矩阵快速幂)
- JS学习之路系列总结四象阵(此文犹如武林之中的易筋经,是你驰骋IT界的武功心法,学会JS五大阵法就学会了JS,博主建议先学三才阵)...
- uni-app学习 组件---a链接的跳转(四)
- 附录:入行 AI,选个脚踏实地的岗位
- 嵌入式Linux磁盘(硬盘、SD卡)读写性能测试
- chrome图片下载插件
- [LeetCode]Medium - Cutting Ribbons - python
- HTML5学习笔记(三)
- 课程设计每日总结0820