当前位置:   article > 正文

C++Windows下用Winsock创建的Socket服务端和客户端_windows c++socket例子

windows c++socket例子

 服务端代码,由于recv和send用的是阻塞函数,考虑用多线程开两个子线程分别读写

服务端:

头文件Server.h

  1. #include <WinSock2.h>
  2. #include <iostream>
  3. #include <vector>
  4. #pragma comment(lib,"ws2_32.lib")
  5. using namespace std;
  6. #define PORT 7777
  7. DWORD WINAPI SendMessage(LPVOID LParam)
  8. {
  9. SOCKET* sockClient = (SOCKET*)LParam;
  10. //登录初始化
  11. char recvBuf[100];
  12. memset(recvBuf,0,sizeof(recvBuf));
  13. char sendbuf[] = "服务器连接成功!欢迎... ...\n输入bye退出";
  14. int ret = send(*sockClient,sendbuf,sizeof(sendbuf),0);
  15. if(ret == SOCKET_ERROR)
  16. {
  17. cout << "Send data failed ... ..." <<endl;
  18. return -1;
  19. }
  20. while(strcmp(sendbuf,"bye")!=0)
  21. {
  22. //============== send() ==============
  23. memset(sendbuf,0,sizeof(sendbuf));
  24. cin >> sendbuf;
  25. ret = send(*sockClient,sendbuf,sizeof(sendbuf),0);
  26. if(ret == SOCKET_ERROR)
  27. {
  28. cout << "Send data failed ... ..." <<endl;
  29. return -2;
  30. }
  31. }
  32. return NULL;
  33. }
  34. DWORD WINAPI ReceiveMessage(LPVOID LParam)
  35. {
  36. SOCKET* sockClient = (SOCKET*)LParam;
  37. char receivebuf[2048];
  38. int ret = 0;
  39. while(strcmp(receivebuf,"bye")!=0)
  40. {
  41. //============== recv() ==============
  42. memset(receivebuf,0,sizeof(receivebuf));
  43. ret = recv(*sockClient,receivebuf,sizeof(receivebuf),0);
  44. if(ret >=0 )
  45. {
  46. //cout << "########## receive data(" << ret << " byte) ##########" <<endl;
  47. cout << receivebuf <<endl;
  48. }
  49. }
  50. return NULL;
  51. }
  52. class CServer
  53. {
  54. public:
  55. CServer(int nPort=PORT);
  56. ~CServer();
  57. int Socket();
  58. int Bind();
  59. int Listen();
  60. int Accept();
  61. int CreateConversation();
  62. HANDLE GetSendHandle();
  63. HANDLE GetReceiveHandle();
  64. protected:
  65. private:
  66. HANDLE m_hSendThread;
  67. HANDLE m_hReceiveThread;
  68. DWORD m_dSendThreadId;
  69. DWORD m_dReceiveThreadId;
  70. int m_nPort;
  71. SOCKET sockSrv;
  72. SOCKADDR_IN m_addrSrv;
  73. //客户端信息
  74. SOCKET sockClient;
  75. SOCKADDR_IN m_addrClient;
  76. };

Server.cpp

  1. #include "Server.h"
  2. #include <Windows.h>
  3. DWORD WINAPI CONNECT_POOLING(LPVOID lpParam)
  4. {
  5. return 0;
  6. }
  7. CServer::CServer(int nPort)
  8. {
  9. m_nPort = nPort;
  10. m_hSendThread = NULL;
  11. m_hReceiveThread = NULL;
  12. //初始化IP和port
  13. m_addrSrv.sin_family = AF_INET;
  14. m_addrSrv.sin_port = htons(m_nPort);//1024以上端口号
  15. m_addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
  16. }
  17. CServer::~CServer()
  18. {
  19. m_nPort = 0;
  20. CloseHandle(m_hSendThread);
  21. CloseHandle(m_hReceiveThread);
  22. closesocket(sockClient);
  23. closesocket(sockSrv);
  24. WSACleanup();
  25. }
  26. int CServer::Socket()
  27. {
  28. WSADATA data;
  29. int ret = WSAStartup(MAKEWORD(2,2),&data);
  30. //Debug
  31. /*cout << "Initialization return " << ret << endl;*/
  32. if(ret)
  33. {
  34. cout << "Socket initialization failed: " << WSAGetLastError() << "... ..." << endl;
  35. return -1;
  36. }
  37. sockSrv = socket(AF_INET,SOCK_STREAM,0);
  38. if (SOCKET_ERROR == sockSrv)
  39. {
  40. cout << "Socket create failed: " << WSAGetLastError() << "... ..." << endl;
  41. return -2;
  42. }
  43. return ret;
  44. }
  45. int CServer::Bind()
  46. {
  47. //SOCKET sock = sockSrv;
  48. //============== bind() ==============
  49. int ret = bind(sockSrv,(LPSOCKADDR)&m_addrSrv,sizeof(SOCKADDR_IN));
  50. //Debug
  51. /*cout << "bind return " << ret << endl;*/
  52. if(ret)
  53. {
  54. cout << "Socket bind failed: " << WSAGetLastError() << "... ..." << endl;
  55. return -2;
  56. }
  57. else
  58. {
  59. cout << "Socket bind succeed! " << endl;
  60. }
  61. return ret;
  62. }
  63. int CServer::Listen()
  64. {
  65. //============== listen() ==============
  66. int ret = listen(sockSrv,10);
  67. if(ret == SOCKET_ERROR)
  68. {
  69. cout << "Socket listen failed: " << WSAGetLastError() << "... ..." << endl;
  70. return -3;
  71. }
  72. //begin to listen
  73. cout << "Server start successfully ... ... Begin listening on "<< m_nPort << endl;
  74. return ret;
  75. }
  76. int CServer::Accept()
  77. {
  78. int len = sizeof(SOCKADDR);
  79. //等待客户端connect请求
  80. //============== accept() ==============
  81. sockClient = accept(sockSrv,(LPSOCKADDR)&m_addrClient,&len);
  82. if (sockClient == SOCKET_ERROR)
  83. {
  84. cout << "Build connection failed: " << WSAGetLastError() << "... ..." << endl;
  85. return -1;
  86. }
  87. else
  88. {
  89. printf("Server(%s:%d) build connection with Client at %s:%d\n",
  90. inet_ntoa(m_addrSrv.sin_addr),htons(m_addrSrv.sin_port),
  91. inet_ntoa(m_addrClient.sin_addr),htons(m_addrClient.sin_port));
  92. }
  93. return 0;
  94. }
  95. int CServer::CreateConversation()
  96. {
  97. m_hSendThread = CreateThread(NULL,0,SendMessage,&sockClient,0,&m_dSendThreadId);
  98. m_hReceiveThread = CreateThread(NULL,0,ReceiveMessage,&sockClient,0,&m_dReceiveThreadId);
  99. return 0;
  100. }
  101. HANDLE CServer::GetSendHandle()
  102. {
  103. return m_hSendThread;
  104. }
  105. HANDLE CServer::GetReceiveHandle()
  106. {
  107. return m_hReceiveThread;
  108. }
  109. int Initialize()
  110. {
  111. WSADATA data;
  112. int ret = WSAStartup(MAKEWORD(2,2),&data);
  113. //Debug
  114. /*cout << "Initialization return " << ret << endl;*/
  115. if(ret)
  116. {
  117. cout << "Socket initialization failed: " << WSAGetLastError() << "... ..." << endl;
  118. return -1;
  119. }
  120. return 0;
  121. }
  122. int Start_Server()
  123. {
  124. int ret = 0;
  125. //============== socket() ==============
  126. SOCKET sockSrv = socket(AF_INET,SOCK_STREAM,0);
  127. unsigned long pcmd = NULL;
  128. //Debug
  129. /*ret = sockSrv;
  130. cout << "socket return " << ret << endl;
  131. if(SOCKET_ERROR == ret)
  132. {
  133. cout << "Socket create failed: " << WSAGetLastError() << "... ..." << endl;
  134. }*/
  135. //初始化IP和port
  136. SOCKADDR_IN addrSrv;
  137. addrSrv.sin_family = AF_INET;
  138. addrSrv.sin_port = htons(PORT);//1024以上端口号
  139. addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
  140. //============== bind() ==============
  141. ret = bind(sockSrv,(LPSOCKADDR)&addrSrv,sizeof(SOCKADDR_IN));
  142. //Debug
  143. /*cout << "bind return " << ret << endl;*/
  144. if(ret)
  145. {
  146. cout << "Socket bind failed: " << WSAGetLastError() << "... ..." << endl;
  147. return -2;
  148. }
  149. //============== listen() ==============
  150. ret = listen(sockSrv,10);
  151. if(ret == SOCKET_ERROR)
  152. {
  153. cout << "Socket listen failed: " << WSAGetLastError() << "... ..." << endl;
  154. return -3;
  155. }
  156. //客户端信息
  157. SOCKADDR_IN addrClient;
  158. int len = sizeof(SOCKADDR);
  159. //begin to listen
  160. cout << "Server start successfully ... ... Begin listening" << endl;
  161. while(1)
  162. {
  163. //等待客户端connect请求
  164. //============== accept() ==============
  165. SOCKET sockConn = accept(sockSrv,(LPSOCKADDR)&addrClient,&len);
  166. //ioctlsocket(sockConn,FIONBIO,&pcmd);
  167. if (sockConn == SOCKET_ERROR)
  168. {
  169. cout << "Build connection failed: " << WSAGetLastError() << "... ..." << endl;
  170. break;
  171. }
  172. printf("Server(%s:%d) build connection with Client at %s:%d\n",
  173. inet_ntoa(addrSrv.sin_addr),htons(addrSrv.sin_port),
  174. inet_ntoa(addrClient.sin_addr),htons(addrClient.sin_port));
  175. //登录初始化
  176. char recvBuf[100];
  177. memset(recvBuf,0,sizeof(recvBuf));
  178. char buf[] = "服务器连接成功!欢迎登录... ...\n";
  179. ret = send(sockConn,buf,sizeof(buf),0);
  180. if(ret == SOCKET_ERROR)
  181. {
  182. cout << "Send data failed ... ..." <<endl;
  183. break;
  184. }
  185. while(recvBuf != "bye" || buf != "bye")
  186. {
  187. memset(recvBuf,0,sizeof(recvBuf));
  188. //============== send() ==============
  189. char buf[100];
  190. memset(buf,0,sizeof(buf));
  191. cin >> buf;
  192. ret = send(sockConn,buf,sizeof(buf),0);
  193. if(ret == SOCKET_ERROR)
  194. {
  195. cout << "Send data failed ... ..." <<endl;
  196. break;
  197. }
  198. //============== recv() ==============
  199. ret = recv(sockConn,recvBuf,sizeof(recvBuf),0);
  200. cout << "########## receive data(" << ret << " byte) ##########" <<endl;
  201. cout << recvBuf <<endl;
  202. }
  203. //关闭用于和客户端收发数据而建立的socket
  204. //Linux下一切皆文件,直接用文件操作函数close()关闭socket即可
  205. //============== closesocket() ==============
  206. closesocket(sockConn);
  207. }
  208. //关闭用于监听客户端连接请求的socket
  209. //============== closesocket() ==============
  210. closesocket(sockSrv);
  211. WSACleanup();
  212. cout << "Good Bye!" << endl;
  213. return 0;
  214. }
  215. int main()
  216. {
  217. /*老版读写阻塞
  218. Initialize();
  219. Start_Server();
  220. system("pause");
  221. */
  222. //Winsock服务初始化、创建套接字
  223. cout << "请输入服务器监听端口:" << endl;
  224. int nPort;
  225. cin >> nPort;
  226. CServer oServer = CServer(nPort);
  227. oServer.Socket();
  228. //绑定套接字
  229. oServer.Bind();
  230. //监听套接字
  231. oServer.Listen();
  232. //等待连接
  233. oServer.Accept();
  234. //建立会话
  235. oServer.CreateConversation();
  236. /*Initialize();
  237. Start_Server();*/
  238. WaitForSingleObject(oServer.GetSendHandle(),INFINITE);
  239. WaitForSingleObject(oServer.GetReceiveHandle(),INFINITE);
  240. //system("pause");
  241. return 0;
  242. }

客户端:

Client.h

  1. #include <stdio.h>
  2. #include <WinSock2.h>
  3. #include <iostream>
  4. #pragma comment(lib,"ws2_32.lib")
  5. using namespace std;
  6. #define PORT 7777
  7. DWORD WINAPI SendMessage(LPVOID LParam)
  8. {
  9. SOCKET* sockClient = (SOCKET*)LParam;
  10. char sendbuf[2048];
  11. while(strcmp(sendbuf,"bye")!=0)
  12. {
  13. //========== send() ==========
  14. memset(sendbuf,0,sizeof(sendbuf));
  15. cin >> sendbuf;
  16. send(*sockClient,sendbuf,sizeof(sendbuf),0);
  17. }
  18. return NULL;
  19. }
  20. DWORD WINAPI ReceiveMessage(LPVOID LParam)
  21. {
  22. SOCKET* sockClient = (SOCKET*)LParam;
  23. char receivebuf[2048];
  24. int ret = 0;
  25. while(strcmp(receivebuf,"bye")!=0)
  26. {
  27. //========== recv() ==========
  28. memset(receivebuf,0,sizeof(receivebuf));
  29. ret = recv(*sockClient,receivebuf,sizeof(receivebuf),0);
  30. if(ret >= 0)
  31. {
  32. //cout << "Receiving from the host " << ret << " bytes ... ..." <<endl;
  33. cout << receivebuf <<endl;
  34. }
  35. }
  36. return NULL;
  37. }
  38. class CClient
  39. {
  40. public:
  41. CClient(const char* ip = "127.0.0.1",int nPort = PORT);
  42. ~CClient();
  43. int Socket();
  44. int Connect();
  45. int CreateConversation();
  46. HANDLE GetSendHandle();
  47. HANDLE GetReceiveHandle();
  48. int SetPort(int nPort);
  49. int GetPort();
  50. int SetIP(char ip[]);
  51. const char* GetIP();
  52. protected:
  53. private:
  54. HANDLE m_hSendThread;
  55. HANDLE m_hReceiveThread;
  56. DWORD m_dSendThreadId;
  57. DWORD m_dReceiveThreadId;
  58. int m_nPort;
  59. const char* m_IP;
  60. SOCKET sockClient;
  61. SOCKADDR_IN m_sockAddr;
  62. };
  63. //Winsock服务初始化
  64. int Initialize();
  65. //建立、启动客户端
  66. int Start_Client();

Client.cpp

  1. #include "Client.h"
  2. CClient::CClient(const char* ip,int nPort)
  3. {
  4. m_IP = ip;
  5. m_nPort = nPort;
  6. m_hSendThread = NULL;
  7. m_hReceiveThread = NULL;
  8. //初始化IP和port
  9. m_sockAddr.sin_family = AF_INET;
  10. m_sockAddr.sin_port = htons(m_nPort);//1024以上端口号
  11. m_sockAddr.sin_addr.S_un.S_addr = inet_addr(m_IP);
  12. }
  13. CClient::~CClient()
  14. {
  15. m_nPort = 0;
  16. CloseHandle(m_hSendThread);
  17. CloseHandle(m_hReceiveThread);
  18. closesocket(sockClient);
  19. WSACleanup();
  20. }
  21. int CClient::Socket()
  22. {
  23. WSADATA data;
  24. int ret = WSAStartup(MAKEWORD(2,2),&data);
  25. //Debug
  26. /*cout << "Initialization return " << ret << endl;*/
  27. if(ret)
  28. {
  29. cout << "Socket initialization failed: " << WSAGetLastError() << "... ..." << endl;
  30. return -1;
  31. }
  32. sockClient = socket(AF_INET,SOCK_STREAM,0);
  33. if (SOCKET_ERROR == sockClient)
  34. {
  35. cout << "Socket create failed: " << WSAGetLastError() << "... ..." << endl;
  36. return -2;
  37. }
  38. return ret;
  39. }
  40. int CClient::Connect()
  41. {
  42. int ret = connect(sockClient,(sockaddr *)&m_sockAddr,sizeof(m_sockAddr));
  43. if(ret == INVALID_SOCKET)
  44. {
  45. cout << "Connect to the host(" << this->GetIP() << ":" << this->GetPort() << ")failed: " << WSAGetLastError() << "... ..." << endl;
  46. return -3;
  47. }
  48. else
  49. {
  50. cout << "Connect to the host(" << this->GetIP() << ":" << this->GetPort() << ")succeed! " << endl;
  51. }
  52. return ret;
  53. }
  54. int CClient::CreateConversation()
  55. {
  56. m_hReceiveThread = CreateThread(NULL,0,ReceiveMessage,&sockClient,0,&m_dReceiveThreadId);
  57. m_hSendThread = CreateThread(NULL,0,SendMessage,&sockClient,0,&m_dSendThreadId);
  58. return NULL;
  59. }
  60. HANDLE CClient::GetSendHandle()
  61. {
  62. return m_hSendThread;
  63. }
  64. HANDLE CClient::GetReceiveHandle()
  65. {
  66. return m_hReceiveThread;
  67. }
  68. int CClient::SetPort(int nPort)
  69. {
  70. m_nPort = nPort;
  71. m_sockAddr.sin_port = htons(m_nPort);
  72. return m_nPort;
  73. }
  74. int CClient::GetPort()
  75. {
  76. return m_nPort;
  77. }
  78. int CClient::SetIP(char ip[])
  79. {
  80. m_IP = ip;
  81. m_sockAddr.sin_addr.S_un.S_addr = inet_addr(m_IP);
  82. return 0;
  83. }
  84. const char* CClient::GetIP()
  85. {
  86. return m_IP;
  87. }
  88. int Start_Client()
  89. {
  90. DWORD thread_id = 0;
  91. HANDLE hThread = CreateThread(NULL,0,SendMessage,NULL,0,&thread_id);
  92. CloseHandle(hThread);
  93. int ret = 0;
  94. char buff[2048];
  95. memset(buff,0,sizeof(buff));
  96. //初始化IP和port
  97. SOCKADDR_IN addrSrv;
  98. addrSrv.sin_family = AF_INET;
  99. addrSrv.sin_port = htons(PORT);//1024以上端口号
  100. addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
  101. //========== socket() ==========
  102. SOCKET sockClient = socket(AF_INET,SOCK_STREAM,0);
  103. if (SOCKET_ERROR == sockClient)
  104. {
  105. cout << "Socket create failed: " << WSAGetLastError() << "... ..." << endl;
  106. return -2;
  107. }
  108. //========== connect() ==========
  109. ret = connect(sockClient,(sockaddr *)&addrSrv,sizeof(addrSrv));
  110. if(ret == INVALID_SOCKET)
  111. {
  112. cout << "Connect to the host failed: " << WSAGetLastError() << "... ..." << endl;
  113. return -3;
  114. }
  115. else
  116. {
  117. char buf[2048];
  118. memset(buf,0,sizeof(buf));
  119. while(buff != "bye" || buf != "bye")
  120. {
  121. memset(buf,0,sizeof(buf));
  122. memset(buff,0,sizeof(buff));
  123. //========== recv() ==========
  124. ret = recv(sockClient,buff,sizeof(buff),0);
  125. cout << "Receiving from the host " << ret << " bytes ... ..." <<endl;
  126. cout << buff <<endl;
  127. //========== send() ==========
  128. cin >> buf;
  129. send(sockClient,buf,sizeof(buf),0);
  130. }
  131. }
  132. //关闭用于监听客户端连接请求的socket
  133. //============== closesocket() ==============
  134. closesocket(sockClient);
  135. WSACleanup();
  136. return 0;
  137. }
  138. int main()
  139. {
  140. /*老板读写阻塞
  141. Initialize();
  142. Start_Client();
  143. */
  144. //Winsock服务初始化、创建套接字
  145. char ip[24];
  146. cout << "请输入远程服务器IP:" << endl;
  147. cin >> ip;
  148. int nPort;
  149. cout << "请输入远程服务器端口:" << endl;
  150. cin >> nPort;
  151. CClient oClient = CClient(ip,nPort);
  152. oClient.Socket();
  153. //建立连接
  154. while(oClient.Connect() != 0)
  155. {
  156. //连接失败重新建立连接
  157. cout << "连接失败,请确认IP地址及端口" << endl;
  158. cout << "IP地址:" << ip << "是否正确?" << endl;
  159. char answer[8];
  160. memset(answer,0,sizeof(answer));
  161. while(strcmp(answer,"Y") != NULL && strcmp(answer,"N") != NULL && strcmp(answer,"y") != NULL && strcmp(answer,"n") != NULL)
  162. {
  163. memset(answer,0,sizeof(answer));
  164. cout << "Y/N?" << endl;
  165. cin >> answer;
  166. if(strcmp(answer,"Y") == NULL || strcmp(answer,"y") == NULL)
  167. {
  168. break;
  169. }
  170. else if(strcmp(answer,"N") == NULL || strcmp(answer,"n") == NULL)
  171. {
  172. cout << "请输入正确的IP:" << endl;
  173. cin >> ip;
  174. oClient.SetIP(ip);
  175. }
  176. }
  177. cout << "远程端口:" << nPort << "是否正确?" << endl;
  178. memset(answer,0,sizeof(answer));
  179. while(strcmp(answer,"Y") != 0 && strcmp(answer,"N") != 0 && strcmp(answer,"y") != 0 && strcmp(answer,"n") != 0)
  180. {
  181. memset(answer,0,sizeof(answer));
  182. cout << "Y/N?" << endl;
  183. cin >> answer;
  184. if(strcmp(answer,"Y") == NULL || strcmp(answer,"y") == NULL)
  185. {
  186. break;
  187. }
  188. else if(strcmp(answer,"N") == NULL || strcmp(answer,"n") == NULL)
  189. {
  190. cout << "请输入正确的端口:" << endl;
  191. cin >> nPort;
  192. oClient.SetPort(nPort);
  193. }
  194. }
  195. }
  196. //建立会话
  197. oClient.CreateConversation();
  198. WaitForSingleObject(oClient.GetSendHandle(),INFINITE);
  199. WaitForSingleObject(oClient.GetReceiveHandle(),INFINITE);
  200. //system("pause");
  201. return 0;
  202. }

本地IP测试连接成功,但通过公网IP连不上,没有开端口映射,可以考虑在路由器上设置,以下采用nat123创建了内网穿透。

此方式建的p2p转发需要在客户端机子上再开一个访问者

域名和端口填上以后添加访问,等连接建立上就可以用客户端和服务端建立通讯了(因为是用别的公网服务器转发的,因此IP并非本机外网IP而是用上图的转发IP:127.15.83.54)

 

 

 

 

 

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号