Skip to content

Instantly share code, notes, and snippets.

@SangSama
Created April 29, 2020 04:16
Show Gist options
  • Save SangSama/07b0d2c7a5f35b9c5dd54b991e4406b3 to your computer and use it in GitHub Desktop.
Save SangSama/07b0d2c7a5f35b9c5dd54b991e4406b3 to your computer and use it in GitHub Desktop.
#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