一、服务器部分代码
头文件:server.h
  1. #include <winsock2.h>
  2. #include <stdio.h>
  3. #include <windef.h>
  4. #ifndef TCP_SERVER_H
  5. #define TCP_SERVER_H
  6. #pragma warning(disable : 4996)
  7. #define MAX_CLIENT (100)
  8. #define LISTEN_PORT (60000)
  9. #define CLIENT_TIMEOUT (15 * 60 * 60) /*客户端中断15分钟则服务器自动掉线*/
  10. #define MAX_TCP_PACKET_SIZE (1492)/*tcp最大数据包字节数*/
  11. typedef struct __client_item
  12. {
  13. SOCKET client;
  14. sockaddr_in form;
  15. unsigned int id;
  16. DWORD dwThreadId;
  17. HANDLE hThread;
  18. }_client_item;
  19. typedef struct __client_list
  20. {
  21. DWORD client_cnt;
  22. _client_item client_item[MAX_CLIENT];
  23. }_client_list;
  24. DWORD WINAPI serve_client_thread_func( LPVOID param_ptr );
  25. #endif/*TCP_SERVER_H*/
源文件:server.cpp
  1. #include "server.h"
  2. #include <sys\stat.h>
  3. #include <time.h>
  4. _client_list client_list;
  5. CRITICAL_SECTION cs_serve_main;
  6. CRITICAL_SECTION cs_serve_thread;
  7. _client_list *get_client_list(void)
  8. {
  9. return &client_list;
  10. }
  11. void client_list_cnt_inc(void)
  12. {
  13. _client_list *client_list_ptr = get_client_list();
  14. client_list_ptr->client_cnt++;
  15. }
  16. void client_list_cnt_dec(void)
  17. {
  18. _client_list *client_list_ptr = get_client_list();
  19. client_list_ptr->client_cnt--;
  20. }
  21. unsigned int get_free_client_index(void)
  22. {
  23. int i = 0;
  24. unsigned int id = 0;
  25. _client_list *client_list_ptr = get_client_list();
  26. for(i = 0; i < MAX_CLIENT; i++)
  27. {
  28. id = client_list_ptr->client_item[i].id;
  29. if( UINT_MAX == id )
  30. {
  31. break;
  32. }
  33. }
  34. return i;
  35. }
  36. _client_item *get_client_item(unsigned int index)
  37. {
  38. _client_list *client_list_ptr = get_client_list();
  39. if( index >= MAX_CLIENT )
  40. {
  41. return NULL;
  42. }
  43. return &client_list_ptr->client_item[index];
  44. }
  45. void set_client_item(unsigned int index, _client_item *client_item_ptr)
  46. {
  47. _client_list *client_list_ptr = get_client_list();
  48. if( index >= MAX_CLIENT )
  49. {
  50. return;
  51. }
  52. client_list_ptr->client_item[index] = *client_item_ptr;
  53. }
  54. SOCKET g_sk_server;
  55. int main()
  56. {
  57. SOCKET server;
  58. WSADATA wsaData;
  59. sockaddr_in local;
  60. int nRet = 0;
  61. int sockaddr_in_sizeof = 0;
  62. unsigned int index = 0;
  63. _client_item *client_item_ptr = NULL;
  64. _client_item client_item = {0};
  65. _client_list *client_list_ptr = NULL;
  66. SOCKET client;
  67. sockaddr_in from;
  68. DWORD dwThreadId;
  69. HANDLE hThread;
  70. nRet = WSAStartup(0x101, &wsaData);
  71. if( 0 != nRet )
  72. {
  73. return 0;
  74. }
  75. // 现在我们来为sockaddr_in结构赋值。
  76. local.sin_family = AF_INET; // 地址族
  77. local.sin_addr.s_addr = INADDR_ANY; // 网际IP地址
  78. local.sin_port = htons(LISTEN_PORT); // 使用的端口
  79. // 由socket函数创建我们的SOCKET。
  80. server = socket(AF_INET, SOCK_STREAM, 0);
  81. //server = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP,NULL, 0, WSA_FLAG_OVERLAPPED);
  82. // 如果socket()函数失败,我们就退出。
  83. if( server == INVALID_SOCKET )
  84. {
  85. return 0;
  86. }
  87. // bind将我们刚创建的套接字和sockaddr_in结构联系起来。
  88. // 它主要使用本地地址及一个特定的端口来连接套接字。
  89. // 如果它返回非零值,就表示出现错误。
  90. nRet = bind(server, (sockaddr*)&local, sizeof(local));
  91. if( 0 != nRet )
  92. {
  93. return 0;
  94. }
  95. // listen命令套接字监听来自客户端的连接。
  96. // 第二个参数是最大连接数。
  97. nRet = listen(server, MAX_CLIENT);
  98. if( 0 != nRet )
  99. {
  100. return 0;
  101. }
  102. g_sk_server = server;
  103. // 我们需要一些变量来保存客户端的套接字,因此我们在此声明之。
  104. InitializeCriticalSection(&cs_serve_main);/*初始化临界区*/
  105. InitializeCriticalSection(&cs_serve_thread);/*初始化临界区*/
  106. client_list_ptr = get_client_list();
  107. memset(client_list_ptr, 0xff, sizeof(_client_list));
  108. memset(&client, 0, sizeof(SOCKET));
  109. memset(&from, 0, sizeof(sockaddr_in));
  110. sockaddr_in_sizeof = sizeof(sockaddr_in);
  111. while( TRUE )
  112. {
  113. index = get_free_client_index();
  114. if( index >= MAX_CLIENT )
  115. {/*已经达到最大连接数*/
  116. continue;
  117. }
  118. client_item_ptr = get_client_item(index);
  119. client_item_ptr->client = accept(server,
  120. (struct sockaddr*)&client_item_ptr->form, &sockaddr_in_sizeof);
  121. if( INVALID_SOCKET == client_item_ptr->client )
  122. {/*连接错误*/
  123. Sleep(500);
  124. continue;
  125. }else
  126. {
  127. printf("Connection from %s\n", inet_ntoa(client_item_ptr->form.sin_addr) );
  128. }
  129. /* 多线程开始*/
  130. EnterCriticalSection(&cs_serve_main);/*进入临界区*/
  131. hThread = CreateThread(
  132. NULL, // no security attributes
  133. 0, // use default stack size
  134. serve_client_thread_func, // thread function
  135. client_item_ptr, // argument to thread function
  136. CREATE_SUSPENDED, // use default creation flags
  137. &dwThreadId); // returns the thread identifier
  138. if( NULL != hThread )
  139. {
  140. client_item_ptr->hThread = hThread;
  141. client_item_ptr->dwThreadId = dwThreadId;
  142. client_item_ptr->id = index;
  143. }
  144. client_list_cnt_inc();
  145. LeaveCriticalSection(&cs_serve_main);/*离开临界区*/
  146. if( NULL != client_item_ptr->hThread )
  147. {
  148. ResumeThread(client_item_ptr->hThread);
  149. }
  150. client_item_ptr = NULL;
  151. /*end 多线程开始*/
  152. }
  153. //关闭套接字,并释放套接字描述符。
  154. closesocket(server);
  155. WSACleanup();
  156. DeleteCriticalSection(&cs_serve_thread);/*删除临界区*/
  157. DeleteCriticalSection(&cs_serve_main);/*删除临界区*/
  158. return 0;
  159. }
  160. void serve_client_thread_clear(SOCKET sock_client,
  161. sockaddr_in *sockaddr_client_ptr,
  162. UINT32 client_id,
  163. char *msg,
  164. _client_item *client_item_ptr
  165. )
  166. {
  167. int msg_len = strlen(msg);
  168. if( msg_len > 0 )
  169. {
  170. send(sock_client, msg, msg_len + 1, 0);
  171. }
  172. closesocket(sock_client);/*关闭连接*/
  173. client_list_cnt_dec();
  174. memset(client_item_ptr, 0, sizeof(_client_item));
  175. set_client_item(client_id, client_item_ptr);
  176. }
  177. DWORD WINAPI serve_client_thread_func(LPVOID param_ptr)
  178. {
  179. char buf[MAX_TCP_PACKET_SIZE];
  180. _client_item *client_item_ptr = (_client_item *)param_ptr;
  181. SOCKET sock_client = 0;
  182. sockaddr_in sockaddr_client = {0};
  183. unsigned int client_id = 0;
  184. _client_list *client_list_ptr = get_client_list();
  185. int recv_size = 0;
  186. time_t sock_free_cur_time = 0;
  187. time_t sock_free_kill_time = 0;
  188. int n_ret = 0;
  189. fd_set fdread;
  190. timeval tv;
  191. while( NULL == client_item_ptr->hThread );
  192. sock_client = client_item_ptr->client;
  193. sockaddr_client = client_item_ptr->form;
  194. client_id = client_item_ptr->id;
  195. sprintf(buf, "%s:%d you id=%d\n", inet_ntoa(sockaddr_client.sin_addr),
  196. sockaddr_client.sin_port, client_id);
  197. send(sock_client, buf, strlen(buf) + 1, 0);
  198. do
  199. {
  200. /*这部分代码在此处必须每次都执行*/
  201. FD_ZERO(&fdread);//初始化fd_set
  202. FD_SET(sock_client, &fdread);//分配套接字句柄到相应的fd_set
  203. tv.tv_sec = 1;//这里我们打算让select等待1s后返回,避免被锁死,也避免马上返回
  204. tv.tv_usec = 0;
  205. /*end 这部分代码在此处必须每次都执行*/
  206. select(0, &fdread, NULL, NULL, &tv);
  207. n_ret = FD_ISSET(sock_client, &fdread);
  208. if( 0 == n_ret )/*没有数据*/
  209. {
  210. continue;
  211. }
  212. recv_size = recv(sock_client, buf, sizeof(buf), 0);
  213. if( recv_size <= 0)
  214. {/*socket 错误,断开连接并退出*/
  215. /*超时,线程退出*/
  216. printf("client time out ip=%s:port=%d:id=%d\n",
  217. inet_ntoa(sockaddr_client.sin_addr), sockaddr_client.sin_port, client_id);
  218. EnterCriticalSection(&cs_serve_thread);/*进入临界区*/
  219. memset(buf, 0, sizeof(buf));
  220. serve_client_thread_clear(sock_client, &sockaddr_client, client_id, buf, client_item_ptr);
  221. LeaveCriticalSection(&cs_serve_thread);/*离开临界区*/
  222. ExitThread(0);/*退出线程*/
  223. }
  224. sock_free_cur_time = 0;
  225. if( ('q' == buf[0]) && (0 == buf[1]) )
  226. {/*客户端主动退出*/
  227. sprintf(buf, "client exit server ip=%s:port=%d:id=%d\n",
  228. inet_ntoa(sockaddr_client.sin_addr), sockaddr_client.sin_port, client_id);
  229. EnterCriticalSection(&cs_serve_thread);/*进入临界区*/
  230. serve_client_thread_clear(sock_client, &sockaddr_client, client_id, buf, client_item_ptr);
  231. LeaveCriticalSection(&cs_serve_thread);/*离开临界区*/
  232. ExitThread(0);/*退出线程*/
  233. }
  234. printf("ip=%s:port=%d:id=%d say:%s\n", inet_ntoa(sockaddr_client.sin_addr),
  235. sockaddr_client.sin_port, client_id, buf);
  236. }while( TRUE );
  237. return 0;
  238. }
2、客户端代码
头文件:client.h
  1. #include <winsock2.h>
  2. #include <stdio.h>
  3. #include <windef.h>
  4. #ifndef TCP_CLIENT_H
  5. #define TCP_CLIENT_H
  6. #pragma warning(disable : 4996)
  7. #define TCP_SERVER_ADDR "192.168.0.2"
  8. #define TCP_SERVER_PORT (60000)
  9. #define MAX_TCP_PACKET_SIZE (1492)/*tcp最大数据包字节数*/
  10. #endif/*end TCP_CLIENT_H*/
源文件:client.cpp
  1. #include "client.h"
  2. int main()
  3. {
  4. int nRet = 0;
  5. WORD wVersionRequested;//版本号
  6. WSADATA wsaData;
  7. SOCKET sock;
  8. SOCKADDR_IN server_addr;
  9. char buf[MAX_TCP_PACKET_SIZE];
  10. int recv_size = 0;
  11. wVersionRequested = MAKEWORD(1, 1);//1.1版本的套接字
  12. nRet = WSAStartup(wVersionRequested, &wsaData);
  13. if( nRet )
  14. {
  15. return nRet;
  16. }
  17. if (LOBYTE(wsaData.wVersion) != 1 ||
  18. HIBYTE(wsaData.wVersion) != 1)
  19. {
  20. return -1;
  21. }//判断高低字节是不是1,如果不是1.1的版本则退出
  22. sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  23. if( INVALID_SOCKET == sock )
  24. {
  25. return -1;
  26. }
  27. server_addr.sin_addr.S_un.S_addr = inet_addr(TCP_SERVER_ADDR);
  28. server_addr.sin_family = AF_INET;
  29. server_addr.sin_port = htons(TCP_SERVER_PORT);
  30. nRet = connect(sock, (SOCKADDR*)&server_addr, sizeof(SOCKADDR) );
  31. if( 0 != nRet )
  32. {
  33. return nRet;
  34. }
  35. recv(sock, buf, sizeof(buf), 0);
  36. printf(buf);
  37. do
  38. {
  39. memset(buf, 0, sizeof(buf));
  40. printf("please write some thing:");
  41. gets(buf);
  42. send(sock, buf, strlen(buf) + 1, 0);
  43. if( ('q'== buf[0]) && (0 == buf[1]) )
  44. {
  45. recv_size = recv(sock, buf, sizeof(buf), 0);
  46. printf(buf);
  47. break;
  48. }
  49. }while( TRUE );
  50. closesocket(sock);
  51. WSACleanup();//必须调用这个函数清除参数
  52. return 0;
  53. }

vc简易网络服务器、客户端实现相关推荐

  1. python学习(九) 网络编程学习--简易网站服务器

    python `网络编程`和其他语言都是一样的,服务器这块步骤为: `1. 创建套接字` `2. 绑定地址` `3. 监听该描述符的所有请求` `4. 有新的请求到了调用accept处理请求` Pyt ...

  2. python网络平台_python学习(九) 网络编程学习--简易网站服务器

    python `网络编程`和其他语言都是一样的,服务器这块步骤为: `1. 创建套接字` `2. 绑定地址` `3. 监听该描述符的所有请求` `4. 有新的请求到了调用accept处理请求` Pyt ...

  3. python应用系列教程——python使用SocketServer实现网络服务器,socket实现客户端

    全栈工程师开发手册 (作者:栾鹏) python教程全解 python使用SocketServer实现网络服务器 SocketServer简化了网络服务器的编写.在进行socket创建时,使用Sock ...

  4. c++网络编程:实现简单的聊天——基于服务器/客户端的模式

    c++ socket编程 服务器/客户端 最近在学c++网路编程,写个帖子记录自己的学习过程,部分内容参考一个博主的,附上他的链接: link 实现: 客户端往服务器端发送一条数据,服务器端接收数据并 ...

  5. Unity网络--HLAPI(1):服务器客户端变量同步,脏标识以及定制特性SyncVar

    服务器客户端变量同步 在网络游戏中,大部分事务都是在服务器内处理的,例如NPC被玩家攻击后减HP,服务器需要将变化的HP值传到各个客户端,客户端更新此HP值后,客户端才会显示减血后的NPC血量,这种同 ...

  6. linux tcp客户端端口号,Linux网络编程--服务器客户端(TCP实现)

    Linux下的一个服务器客户端的小程序,基于TCP的实现:服务器可以同时接受多个客户的接入,通过子进程处理客户请求,下面的例子中,服务器只将客户的IP和端口以及发送的信息显示,然后原样的将客户发送的信 ...

  7. cefsharp 发送请求服务器_使用 WPF 版简易 SIP 服务器向 GB28181 摄像头发送直播请求...

    使用 WPF 版简易 SIP 服务器向 GB28181 摄像头发送直播请求 目录 一.引言 二.项目渊源 三.软件使用及 SIP INVITE 流程 (一) 注册和心跳 (二) 直播 INVITE 四 ...

  8. 如何编写一个简易网络爬虫

    感谢小臣投稿 本文将简述网络爬虫及其工作流程,结合个人实践,简单介绍如何使用HttpClient.HtmlParser第三方jar工具包,编写一个简易的网络爬虫. 网络爬虫简述及流程架构 网络爬虫,又 ...

  9. Java小程序之简易网络画板

    Java小程序之简易网络画板 一.前言: Java是一门网络编程语言,强大的网络可以让数据进行传送:今天,我们就小试牛刀,看看Java是如何进行网络传输数据的: 二.项目分析: 1.功能需求: 我们前 ...

最新文章

  1. Unity 2021创建2D休闲点击器游戏视频教程
  2. 三步10分钟搞定数据库版本的降迁 (将后台数据库SQL2008R2降为SQL2005版本)
  3. 一维随机变量及其概率分布
  4. 拦截器HandlerInterceptor、ResponseBodyAdvice和@ExceptionHandler执行顺序
  5. 表的插入、更新、删除、合并操作_20_通过表关联删除多张表
  6. ORACLE ORA-02030: can only select from fixed tables/views
  7. string.Split(params char[])”最匹配的重载方法具有一些无效参数
  8. linux 查看ip_如何在 Linux 中查看可用的网络接口 | Linux 中国
  9. chart.js x轴显示不全_机床大讲堂第67讲——基于FANUC系统的数控铣床增加第四轴的方法...
  10. 1.无重复字符的最长子串
  11. day46-CSS3新增功能
  12. 用VB无窗口透明Usercontrol编写透明浮动按钮
  13. 爬虫是后端吗_北京市互联网后端职位招聘需求分析
  14. Spring-IOC本质
  15. Java语句详解(图解java语句概念、快速掌握java基础知识点)——Java基础系列
  16. AttributeError: 'list' object has no attribute 'send_keys',python+selenium 实现QQ空间网页的自动登陆。
  17. Gym 100781A Adjoin the Networks——树的直径
  18. charles——教程——转载
  19. 畅购商城-添加订单实现(一)
  20. Halcon复习专题-镜头/匹配/标定/边缘/拟合/缺陷检测/

热门文章

  1. Babel的安装和使用
  2. 用CMake编译运行在网上下载的源文件src
  3. 走近人脸检测:从VJ到深度学习(下)
  4. Caffe学习系列(18): 绘制网络模型
  5. 基于当前分支的某一个commit号创建分支
  6. Spring - Java/J2EE Application Framework 应用框架 第 18 章 使用Quartz或Timer完成时序调度工作
  7. 简明python教程 --C++程序员的视角(一):数值类型、字符串、运算符和控制流
  8. 趣味编程:从字符串中提取信息(参考答案 - 下)
  9. 06_Dart异常处理
  10. “生于忧患,死于安乐”之程序员人生