• C++ TCP通信


    TCP协议:

            服务器 Server                                                客户端 Client

    1.     确定协议版本                                           1.     确定协议版本

    2.      创建socket                                              2.      创建socket

    3.      确定协议地址簇                                       3.      获取服务器地址

    4.      绑定                                                    

    5.     监听

    6.     接受客户端连接                                        4.     连接服务器

    7.     通信                                                          5.     通信

    8.    关闭socket                                                 6.    关闭socket

    9.    清理协议版本信息                                      7.    清理协议版本信息       

    用vs2019写的

    单个服务器,单个客户端

    Server.cpp

    1. #define _WINSOCK_DEPRECATED_NO_WARNINGS
    2. #include
    3. #include
    4. #pragma comment(lib,"ws2_32.lib")
    5. #include
    6. #include
    7. #include
    8. int main()
    9. {
    10. // 1. 确定协议版本
    11. WSADATA wsaData;
    12. WSAStartup(MAKEWORD(2, 2), &wsaData);
    13. if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
    14. {
    15. printf("请求的版本不是2.2版本!\n");
    16. WSACleanup();
    17. return -1;
    18. }
    19. printf("请求的版本为2.2版本!\n");
    20. // 2 创建socket
    21. SOCKET sSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //结构体
    22. if (SOCKET_ERROR == sSocket)
    23. {
    24. printf("创建socke失败 :%d\n",GetLastError());
    25. return -2;
    26. }
    27. printf("创建socke成功!\n");
    28. // 3 确定服务器的协议地址簇
    29. std::string ip = "127.0.0.1";
    30. int port = 8080;
    31. SOCKADDR_IN addr = {0};
    32. addr.sin_family = AF_INET; // 和socket函数第一个参数保持一致
    33. addr.sin_addr.S_un.S_addr = inet_addr(ip.c_str()); //
    34. addr.sin_port = htons(port); //
    35. // 4 绑定
    36. int r = bind(sSocket,(sockaddr*)&addr, sizeof(addr));
    37. if (-1 == r)
    38. {
    39. printf("绑定失败:%d\n",GetLastError());
    40. // 8 断开连接
    41. closesocket(sSocket);
    42. // 9 清理协议版本信息
    43. WSACleanup();
    44. return -2;
    45. }
    46. printf("绑定成功!\n");
    47. // 5. 监听
    48. r = listen(sSocket,10);
    49. if (-1 == r)
    50. {
    51. printf("监听失败:%d\n",GetLastError());
    52. // 8 断开连接
    53. closesocket(sSocket);
    54. // 9 清理协议版本信息
    55. WSACleanup();
    56. return -2;
    57. }
    58. printf("监听成功!\n");
    59. // 6 等待客户端连接
    60. SOCKET cSocket = accept(sSocket,NULL,NULL);
    61. if (SOCKET_ERROR == cSocket)
    62. {
    63. printf("服务器崩溃:%d\n",GetLastError());
    64. // 8 断开连接
    65. closesocket(sSocket);
    66. // 9 清理协议版本信息
    67. WSACleanup();
    68. return -2;
    69. }
    70. printf("有客户端连接上服务器了!\n");
    71. // 7 通信
    72. char buff[256] = {0};
    73. while (1)
    74. {
    75. r = recv(cSocket,buff,255,NULL); // 从客户端接收数据
    76. if (r>0)
    77. {
    78. buff[r] = 0; // 添加结束符号
    79. printf(">>%s\n",buff); // 输出
    80. }
    81. }
    82. while (1);
    83. return 0;
    84. }

    Client.cpp

    1. #define _WINSOCK_DEPRECATED_NO_WARNINGS
    2. #include
    3. #pragma comment(lib,"ws2_32.lib")
    4. #include
    5. #include
    6. #include
    7. int main()
    8. {
    9. // 1. 确定协议版本
    10. WSADATA wsaData;
    11. WSAStartup(MAKEWORD(2, 2), &wsaData);
    12. if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
    13. {
    14. printf("请求的版本不是2.2版本!\n");
    15. WSACleanup();
    16. return -1;
    17. }
    18. printf("请求的版本为2.2版本!\n");
    19. // 2 创建socket
    20. SOCKET sSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    21. if (SOCKET_ERROR == sSocket)
    22. {
    23. printf("创建socke失败 :%d\n", GetLastError());
    24. return -2;
    25. }
    26. printf("创建socke成功!\n");
    27. // 3 确定服务器的协议地址簇
    28. std::string ip = "127.0.0.1";
    29. int port = 8080;
    30. SOCKADDR_IN addr = { 0 };
    31. addr.sin_family = AF_INET; // 和socket函数第一个参数保持一致
    32. addr.sin_addr.S_un.S_addr = inet_addr(ip.c_str()); // 服务器IP地址
    33. addr.sin_port = htons(port); //
    34. // 4 连接
    35. int r = connect(sSocket, (sockaddr*)&addr, sizeof(addr));
    36. if (-1 == r)
    37. {
    38. printf("连接失败:%d\n", GetLastError());
    39. return -2;
    40. }
    41. printf("连接成功!\n");
    42. // 5. 通信
    43. char buff[256];
    44. while (1)
    45. {
    46. memset(buff, 0, 256); // 清空数组
    47. printf("发送服务器信息:");
    48. scanf_s("%s", buff,sizeof(buff));
    49. send(sSocket, buff, strlen(buff), NULL);
    50. }
    51. while (1);
    52. return 0;
    53. }

    多个客户端连接同一个服务器

    Server.cpp

    1. #define _WINSOCK_DEPRECATED_NO_WARNINGS
    2. #include
    3. #include
    4. #pragma comment(lib,"ws2_32.lib")
    5. #include
    6. #include
    7. #include
    8. #define NUM 1024 // 最大连接客户端
    9. SOCKET cSocket[NUM];
    10. int count;
    11. // 和客户端通信的函数
    12. void tongxin(int idx);
    13. int main()
    14. {
    15. count = 0;
    16. // 1. 确定协议版本
    17. WSADATA wsaData;
    18. WSAStartup(MAKEWORD(2, 2), &wsaData);
    19. if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
    20. {
    21. printf("请求的版本不是2.2版本!\n");
    22. WSACleanup();
    23. return -1;
    24. }
    25. printf("请求的版本为2.2版本!\n");
    26. // 2 创建socket
    27. SOCKET sSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //结构体
    28. if (SOCKET_ERROR == sSocket)
    29. {
    30. printf("创建socke失败 :%d\n",GetLastError());
    31. return -2;
    32. }
    33. printf("创建socke成功!\n");
    34. // 3 确定服务器的协议地址簇
    35. std::string ip = "127.0.0.1";
    36. int port = 8080;
    37. SOCKADDR_IN addr = {0};
    38. addr.sin_family = AF_INET; // 和socket函数第一个参数保持一致
    39. addr.sin_addr.S_un.S_addr = inet_addr(ip.c_str()); // 本机IP地址
    40. //addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY); //
    41. addr.sin_port = htons(port); // 大小端转换 在10000左右
    42. //printf("addr = %d \n",sizeof(addr));
    43. // 4 绑定
    44. int r = bind(sSocket,(sockaddr*)&addr, sizeof(addr));
    45. if (-1 == r)
    46. {
    47. printf("绑定失败:%d\n",GetLastError());
    48. // 8 断开连接
    49. closesocket(sSocket);
    50. // 9 清理协议版本信息
    51. WSACleanup();
    52. return -2;
    53. }
    54. printf("绑定成功!\n");
    55. // 5. 监听
    56. r = listen(sSocket,10);
    57. if (-1 == r)
    58. {
    59. printf("监听失败:%d\n",GetLastError());
    60. // 8 断开连接
    61. closesocket(sSocket);
    62. // 9 清理协议版本信息
    63. WSACleanup();
    64. return -2;
    65. }
    66. printf("监听成功!\n");
    67. // 6 等待客户端连接
    68. for(int i =0 ;i < NUM; i++)
    69. {
    70. cSocket[i] = accept(sSocket, NULL, NULL);
    71. if (SOCKET_ERROR == cSocket[i])
    72. {
    73. printf("服务器崩溃:%d\n", GetLastError());
    74. // 8 断开连接
    75. closesocket(sSocket);
    76. // 9 清理协议版本信息
    77. WSACleanup();
    78. return -3;
    79. }
    80. printf("有客户端连接上服务器了: %d \n",i);
    81. count++;
    82. // 创建线程和客户端通信
    83. CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)tongxin, (LPVOID)i, NULL, NULL);
    84. }
    85. while (1);
    86. return 0;
    87. }
    88. // 和客户端通信
    89. void tongxin(int idx)
    90. {
    91. // 7 通信
    92. char buff[256] = { 0 };
    93. int r;
    94. char temp[256];
    95. while (1)
    96. {
    97. r = recv(cSocket[idx], buff, 255, NULL); // 从客户端接收数据
    98. if (r > 0)
    99. {
    100. buff[r] = 0; // 添加结束符号
    101. printf(">>%d:%s\n",idx, buff); // 输出
    102. // 发送给当前连上服务器的所有客户端
    103. memset(temp,0,256);
    104. sprintf(temp, "%d:%s",idx,buff);
    105. for (int i = 0; i < count; i++)
    106. {
    107. send(cSocket[i],temp,strlen(temp),NULL);
    108. }
    109. }
    110. }
    111. }

    Client.cpp

    1. #define _WINSOCK_DEPRECATED_NO_WARNINGS
    2. #include
    3. #pragma comment(lib,"ws2_32.lib")
    4. #include
    5. #include
    6. #include
    7. #include // easyX
    8. SOCKET sSocket;
    9. void scanfAndSend();
    10. int main()
    11. {
    12. initgraph(200,400,1); // 俩个窗口
    13. // 1. 确定协议版本
    14. WSADATA wsaData;
    15. WSAStartup(MAKEWORD(2, 2), &wsaData);
    16. if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
    17. {
    18. printf("请求的版本不是2.2版本!\n");
    19. WSACleanup();
    20. return -1;
    21. }
    22. printf("请求的版本为2.2版本!\n");
    23. // 2 创建socket
    24. sSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    25. if (SOCKET_ERROR == sSocket)
    26. {
    27. printf("创建socke失败 :%d\n", GetLastError());
    28. return -2;
    29. }
    30. printf("创建socke成功!\n");
    31. // 3 确定服务器的协议地址簇
    32. std::string ip = "127.0.0.1";
    33. int port = 8080;
    34. SOCKADDR_IN addr = { 0 };
    35. addr.sin_family = AF_INET; // 和socket函数第一个参数保持一致
    36. addr.sin_addr.S_un.S_addr = inet_addr(ip.c_str()); // 服务器IP地址
    37. //addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY); // 本机IP地址
    38. addr.sin_port = htons(port); // 大小端转换 在10000左右
    39. // 4 连接
    40. int r = connect(sSocket, (sockaddr*)&addr, sizeof(addr));
    41. if (-1 == r)
    42. {
    43. printf("连接失败:%d\n", GetLastError());
    44. return -2;
    45. }
    46. printf("连接成功!\n");
    47. CreateThread(NULL,NULL,(LPTHREAD_START_ROUTINE)scanfAndSend,NULL,NULL,NULL);
    48. char buff[256];
    49. int n = 0;
    50. while (1)
    51. {
    52. r = recv(sSocket,buff,255,NULL); // 循环从服务器接收
    53. if (r>0)
    54. {
    55. buff[r] = 0;// 添加结束符号
    56. // 显示到图形界面窗口
    57. outtextxy(1,n*20,buff);
    58. n++;
    59. if (n>18)
    60. {
    61. n = 0;
    62. cleardevice(); //清屏
    63. }
    64. }
    65. }
    66. while (1);
    67. return 0;
    68. }
    69. void scanfAndSend()
    70. {
    71. // 5. 通信
    72. char buff[256];
    73. while (1)
    74. {
    75. memset(buff, 0, 256); // 清空数组
    76. printf("发送服务器信息:");
    77. scanf_s("%s", buff, sizeof(buff)); // 从命令行窗口接收发给服务器
    78. send(sSocket, buff, strlen(buff), NULL);
    79. }
    80. }

    参考:

    https://www.bilibili.com/video/BV12u411r7J6/?spm_id_from=333.788.top_right_bar_window_custom_collection.content.click&vd_source=701c26bdba61a7e00f00852c31111c06

  • 相关阅读:
    大型网站系统架构演化实例_7.使用NoSQL和搜索引擎
    消息队列的实现
    Seata TCC、Saga、XA模式初识
    Spring 事务(测试)--在这个笔记中记录的是没有添加事务,数据库返回的效果。...
    线性反向传播(机器学习)
    【学习笔记】「JOISC 2017 Day 3」自然公园
    Vue.js+Node.js全栈开发教程:Vue.js指令详解
    【BI看板】superset api接口分析
    Java转义工具类StringEscapeUtils的学习笔记
    麒麟系统开发笔记(十三):在国产麒麟系统上编译OSG库、搭建基础开发环境和移植测试Demo
  • 原文地址:https://blog.csdn.net/qq_42046837/article/details/133847022