測試VC2015開發環境撰寫純C++ multi threaded socket server
測試VC2015開發環境撰寫純C++ multi threaded socket server
資料來源:
windows C++ socket server
https://docs.microsoft.com/zh-tw/windows/win32/winsock/complete-server-code
C++ multi threaded socket server windows
https://stackoverflow.com/questions/56623685/simple-non-blocking-multi-threaded-tcp-server
C++ queue
https://shengyu7697.github.io/std-queue/
C++ thread lock example
https://shengyu7697.github.io/std-mutex/
GITHUB: https://github.com/jash-git/Jash-good-idea-20220401-001/tree/main/20220404%E8%B3%87%E6%96%99%E6%94%B6%E8%97%8F/VC2015CppMultiSocketServer
// VC2015CppMultiSocketServer.cpp : 定義主控台應用程式的進入點。
// https://stackoverflow.com/questions/56623685/simple-non-blocking-multi-threaded-tcp-server
//https://shengyu7697.github.io/std-queue/
#include "stdafx.h"
#include <stdio.h>
#include <iostream>
#include <string>
#include <thread>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <mutex>
#include <queue>
using namespace std;
#pragma comment (lib, "ws2_32.lib")
std::mutex g_mutex;
void pause()
{
printf("Press Enter key to continue..");
fgetc(stdin);
}
void clientSocketHandler(SOCKET clientSocket, std::string client_ip)
{
char buf[4096];
std::thread::id thread_id = std::this_thread::get_id();
std::cout << thread_id << " - " << client_ip << ": connected" << std::endl;
while (true)
{
ZeroMemory(buf, 4096);
int bytesReceived = recv(clientSocket, buf, 4096, 0);
if (bytesReceived == 0)
{
std::cout << thread_id << " - " << client_ip << ": disconnected" << std::endl;
break;
}
if (bytesReceived > 0)
{
std::cout << thread_id << " - " << client_ip << ": " << std::string(buf, 0, bytesReceived) << std::endl;
g_mutex.lock();
//send(clientSocket, buf, bytesReceived + 1, 0);
g_mutex.unlock();
}
}
std::cout << thread_id << " - " << client_ip << ": closing client socket & exiting thread..." << std::endl;
closesocket(clientSocket);
}
void waitForConnections(SOCKET serverSocket)
{
sockaddr_in hint;
hint.sin_family = AF_INET;
hint.sin_port = htons(1337);
hint.sin_addr.S_un.S_addr = INADDR_ANY;
bind(serverSocket, (sockaddr*)&hint, sizeof(hint));
listen(serverSocket, SOMAXCONN);
cout << "TCP Server Listen(port:1337) ..." << endl;
while (true) {
sockaddr_in client;
int clientSize = sizeof(client);
SOCKET clientSocket = accept(serverSocket, (sockaddr*)&client, &clientSize);
if (clientSocket != INVALID_SOCKET)
{
char host[NI_MAXHOST]; // Client's remote name
ZeroMemory(host, NI_MAXHOST); // same as memset(host, 0, NI_MAXHOST);
std::string client_ip = inet_ntop(AF_INET, &client.sin_addr, host, NI_MAXHOST);
std::thread t(clientSocketHandler, clientSocket, client_ip);
t.detach();
}
Sleep(100);
}
}
int main()
{
// Initialze winsock
WSADATA wsData;
WORD ver = MAKEWORD(2, 2);
int wsOk = WSAStartup(ver, &wsData);
if (wsOk != 0)
{
std::cerr << "Can't Initialize winsock! Quitting..." << std::endl;
return 1;
}
// Create a socket
SOCKET serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (serverSocket == INVALID_SOCKET)
{
WSACleanup();
std::cerr << "Can't create a socket! Quitting..." << std::endl;
return 1;
}
// Start listening for connections
waitForConnections(serverSocket);
// Cleanup winsock
WSACleanup();
pause();
return 0;
}