一、服务器部分代码 头文件:server.h源文件:server.cpp
- #include
- #include
- #include
- #ifndef TCP_SERVER_H
- #define TCP_SERVER_H
- #pragma warning(disable : 4996)
- #define MAX_CLIENT (100)
- #define LISTEN_PORT (60000)
- #define CLIENT_TIMEOUT (15 * 60 * 60) /*客户端中断15分钟则服务器自动掉线*/
- #define MAX_TCP_PACKET_SIZE (1492)/*tcp最大数据包字节数*/
- typedef struct __client_item
- {
- SOCKET client;
- sockaddr_in form;
- unsigned int id;
- DWORD dwThreadId;
- HANDLE hThread;
- }_client_item;
- typedef struct __client_list
- {
- DWORD client_cnt;
- _client_item client_item[MAX_CLIENT];
- }_client_list;
- DWORD WINAPI serve_client_thread_func( LPVOID param_ptr );
- #endif/*TCP_SERVER_H*/
- #include "server.h"
- #include
- #include
- _client_list client_list;
- CRITICAL_SECTION cs_serve_main;
- CRITICAL_SECTION cs_serve_thread;
- _client_list *get_client_list(void)
- {
- return &client_list;
- }
- void client_list_cnt_inc(void)
- {
- _client_list *client_list_ptr = get_client_list();
- client_list_ptr->client_cnt++;
- }
- void client_list_cnt_dec(void)
- {
- _client_list *client_list_ptr = get_client_list();
- client_list_ptr->client_cnt--;
- }
- unsigned int get_free_client_index(void)
- {
- int i = 0;
- unsigned int id = 0;
- _client_list *client_list_ptr = get_client_list();
- for(i = 0; i < MAX_CLIENT; i++)
- {
- id = client_list_ptr->client_item[i].id;
- if( UINT_MAX == id )
- {
- break;
- }
- }
- return i;
- }
- _client_item *get_client_item(unsigned int index)
- {
- _client_list *client_list_ptr = get_client_list();
- if( index >= MAX_CLIENT )
- {
- return NULL;
- }
- return &client_list_ptr->client_item[index];
- }
- void set_client_item(unsigned int index, _client_item *client_item_ptr)
- {
- _client_list *client_list_ptr = get_client_list();
- if( index >= MAX_CLIENT )
- {
- return;
- }
- client_list_ptr->client_item[index] = *client_item_ptr;
- }
- SOCKET g_sk_server;
- int main()
- {
- SOCKET server;
- WSADATA wsaData;
- sockaddr_in local;
- int nRet = 0;
- int sockaddr_in_sizeof = 0;
- unsigned int index = 0;
- _client_item *client_item_ptr = NULL;
- _client_item client_item = {0};
- _client_list *client_list_ptr = NULL;
- SOCKET client;
- sockaddr_in from;
- DWORD dwThreadId;
- HANDLE hThread;
- nRet = WSAStartup(0x101, &wsaData);
- if( 0 != nRet )
- {
- return 0;
- }
- // 现在我们来为sockaddr_in结构赋值。
- local.sin_family = AF_INET; // 地址族
- local.sin_addr.s_addr = INADDR_ANY; // 网际IP地址
- local.sin_port = htons(LISTEN_PORT); // 使用的端口
- // 由socket函数创建我们的SOCKET。
- server = socket(AF_INET, SOCK_STREAM, 0);
- //server = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP,NULL, 0, WSA_FLAG_OVERLAPPED);
- // 如果socket()函数失败,我们就退出。
- if( server == INVALID_SOCKET )
- {
- return 0;
- }
- // bind将我们刚创建的套接字和sockaddr_in结构联系起来。
- // 它主要使用本地地址及一个特定的端口来连接套接字。
- // 如果它返回非零值,就表示出现错误。
- nRet = bind(server, (sockaddr*)&local, sizeof(local));
- if( 0 != nRet )
- {
- return 0;
- }
- // listen命令套接字监听来自客户端的连接。
- // 第二个参数是最大连接数。
- nRet = listen(server, MAX_CLIENT);
- if( 0 != nRet )
- {
- return 0;
- }
- g_sk_server = server;
- // 我们需要一些变量来保存客户端的套接字,因此我们在此声明之。
- InitializeCriticalSection(&cs_serve_main);/*初始化临界区*/
- InitializeCriticalSection(&cs_serve_thread);/*初始化临界区*/
- client_list_ptr = get_client_list();
- memset(client_list_ptr, 0xff, sizeof(_client_list));
- memset(&client, 0, sizeof(SOCKET));
- memset(&from, 0, sizeof(sockaddr_in));
- sockaddr_in_sizeof = sizeof(sockaddr_in);
- while( TRUE )
- {
- index = get_free_client_index();
- if( index >= MAX_CLIENT )
- {/*已经达到最大连接数*/
- continue;
- }
- client_item_ptr = get_client_item(index);
- client_item_ptr->client = accept(server,
- (struct sockaddr*)&client_item_ptr->form, &sockaddr_in_sizeof);
- if( INVALID_SOCKET == client_item_ptr->client )
- {/*连接错误*/
- Sleep(500);
- continue;
- }else
- {
- printf("Connection from %s\n", inet_ntoa(client_item_ptr->form.sin_addr) );
- }
- /* 多线程开始*/
- EnterCriticalSection(&cs_serve_main);/*进入临界区*/
- hThread = CreateThread(
- NULL, // no security attributes
- 0, // use default stack size
- serve_client_thread_func, // thread function
- client_item_ptr, // argument to thread function
- CREATE_SUSPENDED, // use default creation flags
- &dwThreadId); // returns the thread identifier
- if( NULL != hThread )
- {
- client_item_ptr->hThread = hThread;
- client_item_ptr->dwThreadId = dwThreadId;
- client_item_ptr->id = index;
- }
- client_list_cnt_inc();
- LeaveCriticalSection(&cs_serve_main);/*离开临界区*/
- if( NULL != client_item_ptr->hThread )
- {
- ResumeThread(client_item_ptr->hThread);
- }
- client_item_ptr = NULL;
- /*end 多线程开始*/
- }
- //关闭套接字,并释放套接字描述符。
- closesocket(server);
- WSACleanup();
- DeleteCriticalSection(&cs_serve_thread);/*删除临界区*/
- DeleteCriticalSection(&cs_serve_main);/*删除临界区*/
- return 0;
- }
- void serve_client_thread_clear(SOCKET sock_client,
- sockaddr_in *sockaddr_client_ptr,
- UINT32 client_id,
- char *msg,
- _client_item *client_item_ptr
- )
- {
- int msg_len = strlen(msg);
- if( msg_len > 0 )
- {
- send(sock_client, msg, msg_len + 1, 0);
- }
- closesocket(sock_client);/*关闭连接*/
- client_list_cnt_dec();
- memset(client_item_ptr, 0, sizeof(_client_item));
- set_client_item(client_id, client_item_ptr);
- }
- DWORD WINAPI serve_client_thread_func(LPVOID param_ptr)
- {
- char buf[MAX_TCP_PACKET_SIZE];
- _client_item *client_item_ptr = (_client_item *)param_ptr;
- SOCKET sock_client = 0;
- sockaddr_in sockaddr_client = {0};
- unsigned int client_id = 0;
- _client_list *client_list_ptr = get_client_list();
- int recv_size = 0;
- time_t sock_free_cur_time = 0;
- time_t sock_free_kill_time = 0;
- int n_ret = 0;
- fd_set fdread;
- timeval tv;
- while( NULL == client_item_ptr->hThread );
- sock_client = client_item_ptr->client;
- sockaddr_client = client_item_ptr->form;
- client_id = client_item_ptr->id;
- sprintf(buf, "%s:%d you id=%d\n", inet_ntoa(sockaddr_client.sin_addr),
- sockaddr_client.sin_port, client_id);
- send(sock_client, buf, strlen(buf) + 1, 0);
- do
- {
- /*这部分代码在此处必须每次都执行*/
- FD_ZERO(&fdread);//初始化fd_set
- FD_SET(sock_client, &fdread);//分配套接字句柄到相应的fd_set
- tv.tv_sec = 1;//这里我们打算让select等待1s后返回,避免被锁死,也避免马上返回
- tv.tv_usec = 0;
- /*end 这部分代码在此处必须每次都执行*/
- select(0, &fdread, NULL, NULL, &tv);
- n_ret = FD_ISSET(sock_client, &fdread);
- if( 0 == n_ret )/*没有数据*/
- {
- continue;
- }
- recv_size = recv(sock_client, buf, sizeof(buf), 0);
- if( recv_size
关注打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?
立即登录/注册


微信扫码登录