• 多线程非阻塞server端


    在非阻塞的accetp成功后就创建一个线程来处理新的客户端,并将客户端socket和地址作为参数传给线程函数.

    在非阻塞的代码中修改一下即可

    示例代码:

    /*
        主线程进行accpet,每次accpet成功后就生成一个线程处理这个连接过来的
        客户端
    */
    #define WIN32_LEAN_AND_MEAN
    #include<iostream>
    #include<string>
    #include<winsock2.h>
    
    using namespace std;
    
    #pragma comment(lib,"ws2_32.lib")
    
    
    DWORD WINAPI handleThreadProc(LPVOID param[])
    {
        char recv_buffer[1024];
        char send_buffer[1024];
        int error_code;                //存储WSAGetLastError()的返回值
        int len = sizeof(SOCKADDR);
        SOCKET client_socket = (SOCKET)param[0];
        SOCKADDR_IN* client_addr=(SOCKADDR_IN*)param[1];
        //解决非阻塞的recv和send
        cout << "connect by " << inet_ntoa(client_addr->sin_addr) << ntohs(client_addr->sin_port) << endl;
        while (1)
        {
            memset(recv_buffer, '', 1024);
            //对于该函数,由于是非阻塞模式,没有数据不会阻塞,错误处理和上面类似
            if (recv(client_socket, recv_buffer, 1024, 0) == SOCKET_ERROR)
            {
                error_code = WSAGetLastError();
                if (error_code == WSAEWOULDBLOCK)
                {
                    Sleep(100);
                    continue;
                }
                else
                {
                    cout << "recv error code is " << error_code << endl;
                    closesocket(client_socket);
                    WSACleanup();
                    return -4;
                }
            }
    
            if (strcmp(recv_buffer, "quit") == 0)
            {
                cout << "客户端退出" << endl;
                closesocket(client_socket);
                return 1;
            }
            else
            {
    
                while (1)
                {
                    cout << "recvice from  :" << inet_ntoa(client_addr->sin_addr) << ntohs(client_addr->sin_port)<<"	" << recv_buffer << endl;
                    cin >> send_buffer;
                    if (send(client_socket, send_buffer, strlen(send_buffer) + 1, 0) == SOCKET_ERROR)
                    {
                        error_code = WSAGetLastError();
                        if (error_code == WSAEWOULDBLOCK)
                        {
                            Sleep(200);
                            continue;
                        }
                        else
                        {
                            cout << "send error code is " << error_code << endl;
                            closesocket(client_socket);
                            return -5;
                        }
                    }
                    break;
                }
            }
        }
        return 1;
    }
    int main()
    {
        WSADATA wsaData;
        if (WSAStartup(MAKEWORD(2, 2), &wsaData))
        {
            cout << "版本错误, error code is " << WSAGetLastError() << endl;
            return 1;
        }
    
    
    
        ULONG noblock = 1;            //非阻塞参数
        SOCKET server_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        SOCKET client_socket;
        SOCKADDR_IN bind_addr;
        SOCKADDR_IN client_addr;
        LPVOID params[2];
        int error_code;                //存储WSAGetLastError()的返回值
        int len = sizeof(SOCKADDR);
    
        //设置非阻塞socket
        if (!ioctlsocket(server_socket, FIONBIO, &noblock))
        {
            cout << "设置非阻塞模式成功" << endl;
        }
        bind_addr.sin_addr.S_un.S_addr = htonl(ADDR_ANY);
        bind_addr.sin_family = AF_INET;
        bind_addr.sin_port = htons(8889);
    
        //绑定ip和端口
        if (bind(server_socket, (sockaddr*)&bind_addr, len) == SOCKET_ERROR)
        {
            cout << "bind error code is " << WSAGetLastError() << endl;
            WSACleanup();
            return -1;
        }
    
        //开始监听
        if (listen(server_socket, 5) == SOCKET_ERROR)
        {
            cout << "listen error code is " << WSAGetLastError() << endl;
            WSACleanup();
            return -2;
        }
    
        //解决非阻塞的accpet
        while (1)
        {
    
            client_socket = accept(server_socket, (sockaddr*)&client_addr, &len);
            if (client_socket == INVALID_SOCKET)
            {
                error_code = WSAGetLastError();
                if (error_code == WSAEWOULDBLOCK)
                {
                    Sleep(100);
                    continue;
                }
                else
                {
                    cout << "accept失败,错误码" << error_code << endl;
                    continue;
                }
            }
            else
            {
                params[0] = (LPVOID)client_socket;
                params[1] = (LPVOID)&client_addr;
                CreateThread(0, 0, (LPTHREAD_START_ROUTINE)handleThreadProc, (LPVOID)params, 0, 0);
            }
            
        }
    
        return 0;
    }
  • 相关阅读:
    【转】Shell编程基础篇-上
    【转】inotify+rsync实现实时同步
    Spring
    jdk,jre,tommcat配置问题
    Java前后台开发
    前端组件学习(一)
    报表工具进阶(二)
    查询时异步刷新问题--用到了ajax
    学习jaspersoft/JasperReport
    利用SQLYog操作数据库mysql
  • 原文地址:https://www.cnblogs.com/freesec/p/6207928.html
Copyright © 2020-2023  润新知