simple multi-thread socket server

// SimpleServer.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <conio.h>
#include "winsock.h"
//#include "afxwin.h"

#pragma comment(lib, "ws2_32.lib")

const int MAXCON = 5;

SOCKET server;

void ErrorHandler(const char *msg);
void StartServerThreadProc(LPVOID param);
void HandleClientThreadProc(LPVOID param);

int _tmain(int argc, _TCHAR* argv[])
{
    int PortNum = 9901;
    DWORD id;

    if (argc == 2)
        PortNum = atoi(argv[1]);

    HANDLE hServer = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)StartServerThreadProc,
        (LPVOID)&PortNum, 0, &id);

    std::cout << "Press ESCAPE to quit ..." << std::endl;
    while(getch() != 27);
    TerminateThread(hServer, 0);
    CloseHandle(hServer);

    closesocket(server);
    WSACleanup();

    std::cout << "Main thread exited." << std::endl;
    //getch();
    return 0;
}

void StartServerThreadProc(LPVOID param)
{
    int PortNum = *(int *)param;
    WSAData w;

    if (WSAStartup(0x101, &w) != 0)
    {
        ErrorHandler("WSAStartup Error.");
        return;
    }

    server = socket(AF_INET, SOCK_STREAM, 0);

    sockaddr_in local;
    local.sin_family = AF_INET;
    local.sin_addr.s_addr = INADDR_ANY;
    local.sin_port = htons(PortNum);

    if (INVALID_SOCKET == server)
    {
        ErrorHandler("Socket initialization Error.");
        return;
    }

    if (bind(server, (struct sockaddr *)&local, sizeof(local)) != 0)
    {
        ErrorHandler("Socket binding Error.");
        return;
    }
    std::cout << "Socket binding to port #" << PortNum << std::endl;

    if (listen(server, MAXCON) != 0)
    {
        ErrorHandler("Socket listening Error.");
        return;
    }
    std::cout << "Socket listen with max conn = " << MAXCON << std::endl;

    SOCKET client;
    SOCKADDR_IN client_addr;
    //if client_addr_len not initialized, will receive from 204.204.204.204 endlessly
    int client_addr_len = sizeof(client_addr);
    char buf[512];
    DWORD thread_id;

    int count = 0;

    while(count < 1000)
    {
        sprintf(buf, "Hello.");
        client = accept(server, (struct sockaddr *)&client_addr, &client_addr_len);
        std::cout << "Connection #" << count << " from " << inet_ntoa(client_addr.sin_addr) << std::endl;
        //send(client, buf, strlen(buf), 0);
        CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)HandleClientThreadProc,
            (LPVOID)client, 0, &thread_id);

        //closesocket(client);
        count++;
    }
}

void HandleClientThreadProc(LPVOID param)
{
    SOCKET client = (SOCKET)param;
    SOCKADDR_IN client_addr;
    memset(&client_addr, 0, sizeof(client_addr));
    int addr_len = sizeof(client_addr);

    char buf[512];
    strcpy(buf, "Server Ready");
    send(client, buf, strlen(buf), 0);
    int n;

    getsockname(client, (struct sockaddr *)&client_addr, &addr_len);

    while (true)
    {
        n = recv(client, buf, 512, 0);

        if (SOCKET_ERROR == n)
            break;

        buf[n] = 0;
        std::cout << "[" << inet_ntoa(client_addr.sin_addr) << "]: "
            << buf << std::endl;
    }

    std::cout << "[" << inet_ntoa(client_addr.sin_addr) << "]: "
        << " disconnected." << std::endl;
    closesocket(client);
}

std::string GetLastErrorMsg()
{
    LPVOID lpMsgBuf;
    if (!FormatMessage(
        FORMAT_MESSAGE_ALLOCATE_BUFFER |
        FORMAT_MESSAGE_FROM_SYSTEM |
        FORMAT_MESSAGE_IGNORE_INSERTS,
        NULL,
        GetLastError(),
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
        (LPTSTR) &lpMsgBuf,
        0,
        NULL ))
    {
        // Handle the error.
        return "";
    }

    std::string ret = std::string((char*)lpMsgBuf);

    // Free the buffer.
    LocalFree( lpMsgBuf );

    return ret;
}

void ErrorHandler(const char *msg)
{
    std::cout << msg << std::endl;
    std::string s = GetLastErrorMsg();
    std::cout << "Last Error: " << s.c_str() << std::endl;
    WSACleanup();
    getch();
}

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值