Created
April 29, 2020 04:16
-
-
Save SangSama/07b0d2c7a5f35b9c5dd54b991e4406b3 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#define _WINSOCK_DEPRECATED_NO_WARNINGS | |
#include <winsock2.h> | |
#pragma warning(disable:4996) | |
#pragma comment(lib, "ws2_32") | |
#define WM_SOCKET WM_USER + 1 | |
BOOL CALLBACK WinProc(HWND, UINT, WPARAM, LPARAM); | |
void RemoveClient(CLIENT_INFO*, int*, int*); | |
typedef struct { | |
SOCKET client; | |
BOOL isRegistered; | |
char* id; | |
} CLIENT_INFO; | |
CLIENT_INFO clients[64]; | |
int numClients = 0; | |
int main() | |
{ | |
WSADATA wsa; | |
WSAStartup(MAKEWORD(2, 2), &wsa); | |
SOCKADDR_IN addr; | |
addr.sin_family = AF_INET; | |
addr.sin_addr.s_addr = htonl(INADDR_ANY); | |
addr.sin_port = htons(9000); | |
SOCKET listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); | |
bind(listener, (SOCKADDR*)&addr, sizeof(addr)); | |
listen(listener, 5); | |
WNDCLASS wndclass; | |
const CHAR* providerClass = "AsyncSelect"; | |
HWND window; | |
wndclass.style = 0; | |
wndclass.lpfnWndProc = (WNDPROC)WinProc; | |
wndclass.cbClsExtra = 0; | |
wndclass.cbWndExtra = 0; | |
wndclass.hInstance = NULL; | |
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); | |
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); | |
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); | |
wndclass.lpszMenuName = NULL; | |
wndclass.lpszClassName = (LPCWSTR)providerClass; | |
if (RegisterClass(&wndclass) == 0) | |
return NULL; | |
// Create a window | |
if ((window = CreateWindow((LPCWSTR)providerClass, L"", WS_OVERLAPPEDWINDOW, | |
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, | |
NULL, NULL, NULL, NULL)) == NULL) | |
return NULL; | |
WSAAsyncSelect(listener, window, WM_SOCKET, FD_ACCEPT); | |
MSG msg; // truyen nhan du lieu | |
while (GetMessage(&msg, NULL, 0, 0) > 0) | |
{ | |
TranslateMessage(&msg); | |
DispatchMessage(&msg); | |
} | |
} | |
BOOL CALLBACK WinProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam) | |
{ | |
int index; | |
if (wMsg == WM_SOCKET) | |
{ | |
// kiem tra loi | |
if (WSAGETSELECTERROR(lParam)) | |
{ | |
closesocket(wParam); | |
return TRUE; | |
} | |
// chap nhan ket noi | |
if (WSAGETSELECTEVENT(lParam) == FD_ACCEPT) | |
{ | |
SOCKET client = accept(wParam, NULL, NULL); | |
printf("New client accepted: %d\n", client); | |
CLIENT_INFO clientInfo; | |
clientInfo.client = client; | |
clientInfo.isRegistered = FALSE; | |
clientInfo.id = NULL; | |
clients[numClients] = clientInfo; | |
numClients++; | |
const char* helloMsg = "Dang nhap theo cu phap \"[client_id:] [your_id]\".\n"; | |
send(client, helloMsg, strlen(helloMsg), 0); | |
WSAAsyncSelect(client, hWnd, WM_SOCKET, FD_READ | FD_CLOSE); // them 2 mat na READ, CLOSE | |
// (soket client, cua so , ma thong diep, su kien) => CALLBACk lai duoc goi | |
} | |
// client dk giai phong ben tren nen se luwu vao wParam | |
if (WSAGETSELECTEVENT(lParam) == FD_READ) | |
{ | |
char buf[256]; | |
const char* errorMsg = "Sai cu phap. Hay nhap lai.\n"; | |
int ret; | |
ret = recv(wParam, buf, sizeof(buf), 0); | |
for (int i = 0; i < numClients; i++) | |
{ | |
if (clients[i].client == wParam) { | |
index = i; | |
break; | |
} | |
} | |
char cmd[16], id[32], tmp[32]; | |
buf[ret] = 0; | |
printf("Received: %s\n", buf); | |
if (!clients[index].isRegistered) { | |
ret = sscanf(buf, "%s %s %s", cmd, id, tmp); | |
// kiem tra cu phap | |
if (ret == 2) { | |
if (strcmp(cmd, "client_id:") == 0) { | |
const char* okMsg = "Dang nhap thanh cong. Hay nhap thong diep de chuyen tiep.\n"; | |
send(wParam, okMsg, strlen(okMsg), 0); | |
clients[index].id = id; | |
clients[index].isRegistered = TRUE; | |
} | |
else { | |
send(wParam, errorMsg, strlen(errorMsg), 0); | |
} | |
}else{ | |
send(wParam, errorMsg, strlen(errorMsg), 0); | |
} | |
} | |
else { | |
char sendBuf[256]; | |
ret = sscanf(buf, "%s", cmd); | |
if (ret == -1 || cmd[0] != '@'){ | |
send(wParam, errorMsg, strlen(errorMsg), 0); | |
} | |
else { | |
char* id = clients[index].id; | |
sprintf(sendBuf, "%s: %s", id, buf + strlen(cmd) + 1); | |
if (strcmp(cmd, "@all") == 0) | |
{ | |
// Chuyen tiep tin nhan den cac client khac | |
for (int i = 0; i < numClients; i++) | |
if (clients[i].client != wParam) | |
send(clients[i].client, sendBuf, strlen(sendBuf), 0); | |
} | |
else | |
{ | |
for (int i = 0; i < numClients; i++) | |
if (strcmp(clients[i].id, cmd + 1) == 0) | |
send(clients[i].client, sendBuf, strlen(sendBuf), 0); | |
} | |
} | |
} | |
} | |
if (WSAGETSELECTEVENT(lParam) == FD_CLOSE) | |
{ | |
RemoveClient(clients, &numClients, &index); | |
closesocket(wParam); | |
} | |
} | |
} | |
void RemoveClient(CLIENT_INFO* clients, int* numClients, int* i) | |
{ | |
if (*i < *numClients - 1) | |
clients[*i] = clients[*numClients - 1]; | |
free(clients[*i].id); | |
*numClients = *numClients - 1; | |
*i = *i - 1; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment