• WinSockAPI多线程服务器


    运行效果:

    程序:

    // TcpServer.cpp : 定义控制台应用程序的入口点。
    //
    
    #include "stdafx.h"
    #include <iostream>
    #include <WinSock2.h>
    #include <Windows.h>
    #include <vector>
    #include <algorithm>
    using namespace std;
    //包含库
    #pragma comment(lib, "ws2_32.lib")
    //发送最大字节数
    #define MAXDATASIZE 100
    #define BACKLOG 100
    const int SERVERPORT = 9999;
    
    //连接数
    static int connum;
    
    //客户端连接线程函数
    DWORD WINAPI qtPingServerThreadFunc(LPVOID lpThreadParameter);
    //客户连接socket数组
    vector<SOCKET> client_fd;
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        int err;
    
        SOCKET sockfd;
    
        struct sockaddr_in local_addr;
        struct sockaddr_in remote_addr;
    
        WORD wRequestVersion;
        WSADATA wsadata;
        wRequestVersion = MAKEWORD(2, 0);
        //启动socket服务
        err = WSAStartup(wRequestVersion, &wsadata);
        if (0 != err)
        {
            printf("Socket Error!
    ");
            return 0;
        }
    
        if (LOBYTE(wsadata.wVersion) != 2 || HIBYTE(wsadata.wVersion) != 0)
        {
            WSACleanup();
            printf("Version Wrong!
    ");
            return 0;
        }
        //创建socket
        sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        
        if (INVALID_SOCKET == sockfd)
        {
            printf("Socket Create Failed!
    ");
            return 0;
        }
        else
        {
            printf("Socket Create Success!
    ");
        }
        //定义服务器地址信息
        local_addr.sin_family = AF_INET;
        local_addr.sin_port = htons(SERVERPORT);
        //INADDR_ANY自动绑定地址
        local_addr.sin_addr.s_addr = INADDR_ANY;//inet_addr("172.16.254.212");
        memset(&(local_addr.sin_zero), 0, 8);
        //绑定socket到本机地址
        if (bind(sockfd, (struct sockaddr *)&local_addr, sizeof(struct sockaddr)) == -1)
        {
            printf("bind wrong!
    ");
            return 0;
        }
        else
        {
            printf("bind success!
    ");
        }
    
        int n = 0;
        unsigned long ul = 1;
        while (1)
        {
            //主线程监听
            if (listen(sockfd, BACKLOG) != -1)
            {
                printf("Listening...
    ");
    
                int sin_size = sizeof(struct sockaddr_in);
                //取出连接的客户端socket
                SOCKET sock = accept(sockfd, (struct sockaddr *)&remote_addr, &sin_size);
                //设置socket为非阻塞
                ioctlsocket(sock,FIONBIO,(unsigned long *)&ul);//
                
                vector<SOCKET>::iterator itr_end = client_fd.end();
                vector<SOCKET>::iterator itr = find(client_fd.begin(), itr_end, sock);
                if (itr == itr_end)
                {
                    client_fd.push_back(sock);
                    printf("receive a connection from %s
    ", inet_ntoa(remote_addr.sin_addr));
                    connum++;
                    
                    printf("当前连接数:%d
    ", connum);
                }
                
                DWORD dwPingThreadID;
                //创建新线程处理该客户socket连接
                HANDLE hPingHandle = CreateThread(0, 0, qtPingServerThreadFunc, (LPVOID)sock, 0, &dwPingThreadID);
            }
            Sleep(50);
        }
    
        for (int i = 0 ; i < client_fd.size(); i++)
        {
            closesocket(client_fd[i]);
        }
        client_fd.clear();
        WSACleanup();
        return 0;
    }
    
    DWORD WINAPI qtPingServerThreadFunc(LPVOID lpThreadParameter)
    {
        SOCKET sock = (SOCKET)lpThreadParameter;
    
        int recvbytes;
        BYTE buf[MAXDATASIZE];
    
        while (1)
        {
            //接收数据
            recvbytes = recv(sock, (char *)buf, MAXDATASIZE, 0);
            //接收到的数据长度为0,则表示客户端主动断开连接
            if (recvbytes == 0)
            {
                printf("disconnect!
    ");
                vector<SOCKET>::iterator itr_end = client_fd.end();
                vector<SOCKET>::iterator itr = find(client_fd.begin(), itr_end, sock);
                if (itr != itr_end)
                {
                    client_fd.erase(itr);
                }
                connum--;
                printf("当前连接数:%d
    ", connum);
                return 0;
            } 
            //接收信息,群发给所有客户端
            else if ((recvbytes) != -1)
            {
                buf[recvbytes] = '';
                printf("Received: %s
    ", buf);
                BYTE * head;
                head = buf;
    
                for (int i = 0; i < client_fd.size(); i++)
                {
                    send(client_fd[i], (char *)buf, sizeof(buf), 0);    
                }
            }
            Sleep(50);
        }
        return 0;
    }
  • 相关阅读:
    R 自定义函数
    order_by 函数 R
    PG 窗口函数实例
    自动化测试学习路线
    .netcore 自带依赖注入
    .net5 Serilog使用
    .net core 读取appsettings.json
    .Net Core Code First
    理解Java中的byte
    Java基础语法1注释、标识符、关键字
  • 原文地址:https://www.cnblogs.com/fwst/p/3731561.html
Copyright © 2020-2023  润新知