Skip to content

Instantly share code, notes, and snippets.

@castaneai
Last active December 15, 2015 12:38
Show Gist options
  • Save castaneai/5261327 to your computer and use it in GitHub Desktop.
Save castaneai/5261327 to your computer and use it in GitHub Desktop.
Winsockで簡易サーバー
/*
コールバック関数を持つサーバーを作れるサンプル
*/
#pragma comment(lib, "ws2_32.lib")
#include <WinSock2.h>
#include <list>
typedef void (*ONRECV)(const SOCKET socket, const char* data, const int data_length);
typedef void (*ONERROR)(const char* message, const int error_code);
void run_server(const char* ip_address, const unsigned short port, ONRECV on_recv, ONERROR on_error)
{
// winsock 初期化
WSADATA d;
WSAStartup(MAKEWORD(2, 0), &d);
// サーバー用ソケット作成
SOCKET server_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
sockaddr_in server_address;
server_address.sin_family = AF_INET;
server_address.sin_addr.S_un.S_addr = inet_addr(ip_address);
server_address.sin_port = htons(port);
if (bind(server_socket, (sockaddr*)&server_address, sizeof(server_address)) != 0) {
on_error("socket bind failed", GetLastError());
return;
}
if (listen(server_socket, 5) != 0) {
on_error("socket listen failed", GetLastError());
}
// ノンブロッキングにする
u_long socket_mode = 1;
ioctlsocket(server_socket, FIONBIO, &socket_mode);
// クライアントリスト
std::list<SOCKET> clients;
while (true) {
// 新しいクライアントの受け入れ
sockaddr_in client_address = {0};
int client_address_length = sizeof(client_address);
SOCKET client = accept(server_socket, (sockaddr*)&client_address, &client_address_length);
if (client != INVALID_SOCKET) {
clients.push_back(client);
}
// 接続済のクライアントからの受信
for (SOCKET client : clients) {
char buffer[0xffff] = {0};
int received_length = recv(client, buffer, 0xffff, 0);
if (received_length < 1 && GetLastError() != WSAEWOULDBLOCK) {
clients.remove(client);
break;
}
if (received_length > 0) {
on_recv(client, buffer, received_length);
}
}
Sleep(10);
}
WSACleanup();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment