Skip to content

Instantly share code, notes, and snippets.

@lehaiquantb
Created May 1, 2020 08:29
Show Gist options
  • Save lehaiquantb/ddcacdfdc4e40ceca0aeeecfd9b6e159 to your computer and use it in GitHub Desktop.
Save lehaiquantb/ddcacdfdc4e40ceca0aeeecfd9b6e159 to your computer and use it in GitHub Desktop.
ChatServer and TelnetServer using WSAsyncSelect
#include <stdio.h>
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <winsock2.h>
#include<iostream>
#include<string>
#include<map>
#define WM_SOCKET WM_USER + 1
using namespace std;
#pragma comment(lib, "ws2_32")
const char* ask = "Enter name ex: \"client_id: xxxxxxxx\":\n";
int num_clients = 0;
map<int, string > ids;//cặp ánh xạ một mã client -> id client
bool check[64];//check[i] = true nếu client[i] nhập đúng cú pháp
SOCKET clients[64];
char buf[256];
//Hàm kiểm tra client có nhập đúng cú pháp
string validate(string syntax) {
if (!syntax.substr(0, 11).compare("client_id: ")) {
return syntax.substr(11);
}
else return "";
}
void removeClient(SOCKET client) {
int i = 0;
for (; i < num_clients; i++)
if (clients[i] == client) break;
if (i < num_clients - 1)
{
clients[i] = clients[num_clients - 1];
}
num_clients--;
}
BOOL CALLBACK WinProc(HWND, UINT, WPARAM, LPARAM);
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;
while (GetMessage(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
BOOL CALLBACK WinProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
{
if (wMsg == WM_SOCKET)
{
if (WSAGETSELECTERROR(lParam))
{
closesocket(wParam);
return TRUE;
}
if (WSAGETSELECTEVENT(lParam) == FD_ACCEPT)
{
SOCKET client = accept(wParam, NULL, NULL);
printf("New client accepted: %d\n", client);
WSAAsyncSelect(client, hWnd, WM_SOCKET, FD_READ | FD_CLOSE);
send(client, ask, strlen(ask), 0);//Hỏi tên client
}
if (WSAGETSELECTEVENT(lParam) == FD_READ)
{
char buf[256];
int ret = recv(wParam, buf, sizeof(buf), 0);
buf[ret - 1] = 0;// Bỏ kí tự xuống dòng và thêm kí tự ngắt xâu
//cout << "received: " << buf << endl;
if (!check[num_clients])//Kiểm tra nếu client chưa được nhập đúng vào server
{
if (validate(buf) == "")//Kiểm tra nếu nhập sai cú pháp
{
send(wParam, ask, strlen(ask), 0);//Hỏi lại client
}
else
{
clients[num_clients] = wParam;
num_clients++;
ids.insert(pair<int, string>((int)wParam, validate(buf)));
check[num_clients] = true;
}
}
else//Nếu client đã được đăng nhập đúng thì dữ tin nhắn được sau đó được gửi cho các client còn lại
{
for (int j = 0; j < num_clients; j++)
{
if (wParam != clients[j])
{
string msg = ids.at((int)wParam) + ":" + buf;
send(clients[j], msg.c_str(), msg.size(), 0);//hàm gửi tin nhắn
}
}
}
}
if (WSAGETSELECTEVENT(lParam) == FD_CLOSE)
{
removeClient(wParam);
closesocket(wParam);
}
}
}
#include <stdio.h>
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <winsock2.h>
#include<iostream>
#include<string>
#include<map>
#include<fstream>
#define WM_SOCKET WM_USER + 1
using namespace std;
#pragma comment(lib, "ws2_32")
const char* askName = "Enter username:\n";
const char* askPass = "Enter password:\n";
int num_clients = 0;
bool check[64]; // = true khi client duoc dang nhap dung user, pass
bool checkUser = true; // trạng thái đăng nhập, true là đang nhập User, ngược lại là nhập password
string user_tmp;//lưu trữ username tạm thời
SOCKET clients[64];
char buf[256];//dữ liệu nhận được
map<string, string> user_pass;
int read_file() {
fstream f_user_pass;
f_user_pass.open("c:\\temp\\userpass.txt");
char user[100];
char pass[100];
if (!f_user_pass.fail())//nếu đọc lỗi thì dừng
{
while (!f_user_pass.eof())//cuối file
{
if (f_user_pass >> user && f_user_pass >> pass) {
user_pass.insert(pair<string, string>(user, pass));
}
else return -1;
}
}
f_user_pass.close();
}
void removeClient(SOCKET client) {
int i = 0;
for (; i < num_clients; i++)
if (clients[i] == client) break;
if (i < num_clients - 1)
{
clients[i] = clients[num_clients - 1];
}
num_clients--;
}
BOOL CALLBACK WinProc(HWND, UINT, WPARAM, LPARAM);
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;
while (GetMessage(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
BOOL CALLBACK WinProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
{
if (wMsg == WM_SOCKET)
{
if (WSAGETSELECTERROR(lParam))
{
closesocket(wParam);
return TRUE;
}
if (WSAGETSELECTEVENT(lParam) == FD_ACCEPT)
{
SOCKET client = accept(wParam, NULL, NULL);
printf("New client accepted: %d\n", client);
WSAAsyncSelect(client, hWnd, WM_SOCKET, FD_READ | FD_CLOSE);
//Hỏi username của client
send(client, askName, strlen(askName), 0);
}
if (WSAGETSELECTEVENT(lParam) == FD_READ)
{
char buf[256];
int ret = recv(wParam, buf, sizeof(buf), 0);
buf[ret - 1] = 0; // Bỏ kí tự xuống dòng và thêm kí tự ngắt xâu
//buf[ret] = 0;
if (!check[num_clients])//nếu client chưa đc đăng nhập
{
if (user_pass.find(buf) != user_pass.end() && checkUser == true)//nhập username
{
send(wParam, askPass, strlen(askPass), 0);//hỏi client Password
user_tmp = buf;
checkUser = false;
}
else if (checkUser == false)//nhập password
{
if (!user_pass.at(user_tmp).compare(buf))//nếu mật khẩu tương ứng với user là đúng
{
check[num_clients] = true;
clients[num_clients] = wParam;
num_clients++;
checkUser = true;
}
else
{
send(wParam, "Wrong password!", 15, 0);
send(wParam, askPass, strlen(askPass), 0);
}
}
else {//chưa đúng user name
send(wParam, "Wrong username!", 15, 0);
send(wParam, askName, strlen(askName), 0);
}
}
else//thực hiện yêu cầu của client đã đăng nhập
{
string buff(buf);
buff = buff + " > c:\\temp\\out.txt";
system(buff.c_str());
}
}
if (WSAGETSELECTEVENT(lParam) == FD_CLOSE)
{
removeClient(wParam);
closesocket(wParam);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment