I want to create two projects with this code so that they can chat with each other, but no matter how much I send, the data does not reach the other client.
I've been thinking and trying for hours on this problem, but it doesn't work. Various multicast chat programs on the web are written in languages other than C++, some use threads and some do not. To the best of my knowledge right now, I can't understand the codes on the web.
For fear of lengthy code, the basic header file and error output function have been omitted.
// header file and function declaration
#define MAXBUF 80
SOCKADDR_IN maddr;
int main(int argc, char* argv[]) {
int port;
cout << "input port number" << endl;
cin >> port;
cout << "use port : " << port << endl;
WSADATA wsa;
if (WSAStartup(MAKEWORD(2, 2), &wsa))
{
err_display("WSAStartup");
return -1;
}
//create send socket
SOCKET r_sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (r_sock == INVALID_SOCKET)
{
err_display(" recv socket");
return -1;
}
//create recv socket
SOCKET s_sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (s_sock == INVALID_SOCKET)
{
err_display(" send socket");
return -1;
}
// bind
maddr.sin_family = AF_INET;
maddr.sin_port = htons(port);
maddr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(r_sock, (SOCKADDR*)&maddr, sizeof(maddr))) {
err_display("bind");
return -1;
}
// Join the Multicast address
const char* mip = "236.0.0.1";
IP_MREQ mreq;
mreq.imr_interface.s_addr = htonl(INADDR_ANY); // s_addr = 주소
// Setting Multicast address
if (!(inet_pton(AF_INET, mip, &mreq.imr_multiaddr))) {
err_display("inet_pton");
return -1;
}
// JOIN
if (setsockopt(r_sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&mreq, sizeof(mreq))) {
err_display("setsockopt");
return -1;
}
while (true) {
HANDLE h1 = (HANDLE)_beginthreadex(NULL, 0, &sendf, (LPVOID)s_sock, 0, NULL);
HANDLE h2 = (HANDLE)_beginthreadex(NULL, 0, &recvf, (LPVOID)r_sock, 0, NULL);
}
closesocket(r_sock);
closesocket(s_sock);
WSACleanup();
return 0;
}
unsigned __stdcall sendf(LPVOID arg) // send thread function
{
SOCKET s_sock = (SOCKET)arg;
char mesbuf[MAXBUF];
int sendlen;
while (1)
{
// send
char mesbuf[MAXBUF];
if (fgets(mesbuf, MAXBUF - 1, stdin) == NULL)
break;
cout << "send Thread" << endl;
sendlen = strlen(mesbuf);
sendto(s_sock, mesbuf, sendlen, 0, (SOCKADDR*)&maddr, sizeof(maddr));
}
return 0;
}
unsigned __stdcall recvf(LPVOID arg) // recv thread function
{
SOCKADDR_IN paddr; // peer address
int namelen = sizeof(paddr);
SOCKET r_sock = (SOCKET)arg;
char mesbuf[MAXBUF];
int recvlen;
while (1)
{
char mesbuf[MAXBUF];
//recive
recvlen = recvfrom(r_sock, mesbuf, MAXBUF - 1, 0, (SOCKADDR*)&paddr, &namelen);
cout << "recv Thread" << endl;
if (recvlen == SOCKET_ERROR) {
err_display("recv error");
closesocket(r_sock);
break;
}
if (recvlen == 0)
{
cout << "normal close connection case" << endl;
closesocket(r_sock);
break;
}
mesbuf[recvlen] = '\0'; // string conversion
cout << "from : " << mesbuf << endl;
}
return 0;
}
Sorry in advance, but please explain, how to use IOCP with WSASend - for example, to send a simple message to the server and receive a response from it.
I am doing this:
Create completion port
Create threads for the completion port
I create a WSASocket, with the Overlaped flag.
I establish a connection with a remote server using WSAConnect
I bind the socket to the completion port.
I send a message to the server - by calling the WSASend function.
Like this:
void My_func_for_Thread(HANDLE iocp)
{
DWORD my_DWORD;
PULONG_PTR my_CompletionKey;
WSAOVERLAPPED* my_WSAOVERLAPPED_1;
int my_GetLastError;
while (1)
{
BOOL my_BOOL_GetQueuedCompletionStatus = GetQueuedCompletionStatus(iocp, &my_DWORD, my_CompletionKey, &my_WSAOVERLAPPED_1, INFINITE);
my_GetLastError = GetLastError();
if (my_BOOL_GetQueuedCompletionStatus == FALSE)
{
std::cout << "GetQueuedCompletionStatus== FALSE" << std::endl;
}
}
}
int main()
{
//-------------------------------------------------------------------Create port IO-------------------------------------------------------------
int Number_Threads = 4;
HANDLE My_handle_IOCP = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, Number_Threads);
//------------------------------------------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------Create thread for IOCP-------------------------------------------------------
std::vector<HANDLE>my_vector_Thread;
for (int i = 0; i < Number_Threads; i++)
{
my_vector_Thread.push_back(CreateThread(0, 0, (LPTHREAD_START_ROUTINE)&My_func_for_Thread, My_handle_IOCP, 0, 0));
}
//---------------------------------------------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------Initialization Winsock-----------------------------------------------------------
WORD my_version_Winsock = MAKEWORD(2, 2);
WSADATA my_wsadata_struct;
int my_WSAStartup = WSAStartup(my_version_Winsock, &my_wsadata_struct);
//------------------------------------------------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------Create WSASocket-----------------------------------------------------------------
SOCKET my_WSASocketA = WSASocketA(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
//--------------------------------------------------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------
std::string myString_IP = "XX.XXX.XX.XXX";
//--------------------------------------------------------------------------
sockaddr my_sockaddr;
my_sockaddr = { 0 };
my_sockaddr.sa_family = 2; // AF_INET.
inet_pton(AF_INET, myString_IP.c_str(), &my_sockaddr.sa_data[2]);
my_sockaddr.sa_data[1] = 80; //http port
//--------------------------------------------------------------------------
int status_WSAConnect = WSAConnect(my_WSASocketA, &my_sockaddr, sizeof(my_sockaddr), NULL, NULL, NULL, NULL);
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------Bind socket and port--------------------------------------------------------
My_handle_Create_IOCP = CreateIoCompletionPort((HANDLE)my_WSASocketA, My_handle_IOCP, NULL, 0);
//-------------------------------------------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------Send message to serever with WSASend-----------------------------------
WSABUF my_WSABUF;
std::string request_text_string = "GET / HTTP/1.1\r\nHost: government.ru\r\nConnection: keep-alive\r\n\r\n";
my_WSABUF.buf = &request_text_string[0];
my_WSABUF.len = request_text_string.size();
WSAOVERLAPPED my_WSAOVERLAPPED;
my_WSAOVERLAPPED = { 0 };
int my_WSASend = WSASend(my_WSASocketA, &my_WSABUF, 1, NULL, 0, &my_WSAOVERLAPPED, NULL);
if (my_WSASend == SOCKET_ERROR)
{
std::cout << "WSASend == SOCKET_ERROR:" std::endl;
}
if (my_WSASend == 0)
{
std::cout << "WSASend == 0: no error" std::endl;
}
//-----------------------------------------------------------------------------------------------------------------------------------------------------------
Sleep(10000);
//---------------------------------------------------------
for (int i = 0; i < Number_Threads; i++)
{
CloseHandle(my_vector_Thread[i]);
}
//---------------------------------------------------------
}
But, GetQueuedCompletionStatus always return 998 - Invalid access to memory location.
Which memory is the disabled access to? What am I doing wrong ?
There are several problems with your code.
Your My_func_for_Thread() function has the wrong signature for use with CreateThread(). The compiler is not complaining because you are using a typecast to silence the compiler from failing.
You are passing an uninitialized pointer to the lpCompletionKey parameter of GetQueuedCompletionStatus(). It expects a pointer to a valid ULONG_PTR variable for it to write to.
The WSAOVERLAPPED needs to remain active in memory until its final status is retrieved from the IOCP queue. But your thread is sleeping much longer than your main() is running. You should allocate the WSAOVERLAPPED dynamically, and then free it when its status is received.
Try something more like this instead:
DWORD WINAPI My_func_for_Thread(LPVOID lpParameter)
{
HANDLE iocp = (HANDLE) lpParameter;
DWORD my_DWORD;
ULONG_PTR my_CompletionKey;
WSAOVERLAPPED* my_WSAOVERLAPPED_1;
DWORD my_GetLastError;
while (TRUE)
{
BOOL my_BOOL_GetQueuedCompletionStatus = GetQueuedCompletionStatus(iocp, &my_DWORD, &my_CompletionKey, (LPOVERLAPPED*) &my_WSAOVERLAPPED_1, INFINITE);
my_GetLastError = GetLastError();
if (my_BOOL_GetQueuedCompletionStatus)
{
delete my_WSAOVERLAPPED_1;
}
else
{
std::cout << "GetQueuedCompletionStatus == FALSE" << std::endl;
}
}
return 0;
}
int main()
{
...
for (int i = 0; i < Number_Threads; i++)
{
HANDLE hThread = CreateThread(NULL, 0, &My_func_for_Thread, My_handle_IOCP, 0, NULL);
if (hThread)
my_vector_Thread.push_back(hThread);
}
...
std::string request_text_string = "GET / HTTP/1.1\r\nHost: government.ru\r\nConnection: keep-alive\r\n\r\n";
WSABUF my_WSABUF;
my_WSABUF.buf = &request_text_string[0];
my_WSABUF.len = request_text_string.size();
WSAOVERLAPPED *my_WSAOVERLAPPED = new WSAOVERLAPPED;
*my_WSAOVERLAPPED = { 0 };
int my_WSASend = WSASend(my_WSASocketA, &my_WSABUF, 1, NULL, 0, my_WSAOVERLAPPED, NULL);
// wait for request to finish...
// wait for response to arrive...
// close socket...
// wait for threads to terminate...
...
for (size_t i = 0; i < my_vector_Thread.size(); i++)
{
CloseHandle(my_vector_Thread[i]);
}
return 0;
}
I have a program that I want to automatically terminate on a WM_POWERBROADCAST message. For some reason, however, it is not terminating when I cause the computer to sleep. The program should have more than enough time to respond to this call, but I don't think the program is processing the message at all. I believe this mainly because the program doesn't terminate when the computer resumes, either, and the message should at least be in the window's queue.
What am I doing wrong that is causing my program not to be able to process this message?
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
switch (message) {
case WM_POWERBROADCAST:
DestroyWindow(hWnd);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_CLOSE:
return 0;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
//Set title of program
//SetConsoleTitleA("Star");
//FreeConsole();
//Change the current directory of the program back to the appropriate folder
wchar_t* UserProf;
SHGetKnownFolderPath(FOLDERID_Profile, 0, NULL, &UserProf);
const wchar_t* EndProf = L"\\AppData\\UserUpdates";
wcsncat(UserProf, EndProf, 23);
wstring ws(UserProf);
string wstr(ws.begin(), ws.end());
//cout << wstr << endl;
SetCurrentDirectoryA(wstr.c_str());
WNDCLASSW WindowClass{CS_NOCLOSE, WindowProc, 0, 0, hInstance, NULL, LoadCursor(nullptr, IDC_ARROW), NULL, NULL, L"chakra"};
RegisterClass(&WindowClass);
HWND hWnd = CreateWindow(L"chakra", L"star", WS_POPUP, 0, 0, 10, 10, NULL, NULL, hInstance, NULL);
ShowWindow(hWnd, SW_HIDE);
string ipAddress = "10.0.0.201"; //IP address of my computer on local network
int port = 13777;
Hunter:
WSAData data;
WORD ver = MAKEWORD(2, 2);
int wsResult = WSAStartup(ver, &data);
if (wsResult != 0) {
//cerr << "Can't start Winsock, Err#" << wsResult << endl;
return 0;
}
SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == INVALID_SOCKET) {
//cerr << "Can't create socket" << endl;
return 0;
}
sockaddr_in hint;
hint.sin_family = AF_INET;
hint.sin_port = htons(port);
inet_pton(AF_INET, ipAddress.c_str(), &hint.sin_addr);
int connCounter = 0;
//Constantly attempts to connect to server
do {
int connResult = connect(sock, (sockaddr*)&hint, sizeof(hint));
if (connResult == SOCKET_ERROR) {
connCounter = 0;
closesocket(sock);
WSACleanup();
goto Hunter;
}
else {
connCounter = 1;
}
} while (connCounter == 0);
char buf[1024]; //Where message from server will be stored
char* pbuf{ buf };
//Things to compare
const char* CreateAccount = "create"; //Server tells client to make IG account
const char* CheckStatus = "check"; //Client tells server if account is running or not
const char* Info = "info"; //Client sends Username and Password of account to server
const char* Run = "run"; //Tells client to start running the account
const char* Kill = "kill"; //Kills program on client for around a month
const char* Settings = "settings"; //Server sets settings for account to run on
string TryAgain = "#13 Not a valid input, either type [check] to check if the account is running, type [create] to create new account, or type [info] for account information\n";
string accInfoSuccess = "#777 You have successfully entered the information for the account (^.^)\n";
string settingsInfoSuccess = "#777 You have successfully set the settings for this account (^.^)\n";
string accInfoProblem = "#13 There was a problem in either saving the information to this account or the account creation program. Type [create] and try again (T.T)\n";
string settingsInfoProblem = "#13 There was a problem in saving the account settings. Type [settings] and try again (T.T)\n";
string accRun = "#777 The account is currently running! ~(^.^)~\n";
string accNoRun = "#13 Sorry the account isn't running, type [run] to run the account (O.o)\n";
string accNoInfo = "#13 There is no info for an account that can be run. Type [create] to make information (\".\")\n";
string accRunErr = "#13 There is a problem with opening the main bot program, try again. If this problem persists, there is an issue clientside V(T.T)V\n";
int loopCounter = 0;
//int on = 1;
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)TRUE, sizeof(TRUE));
MSG Msg = { 0 };
do {
ZeroMemory(buf, 1024);
u_long block = 0;
ioctlsocket(sock, FIONBIO, &block);
DWORD timeout = 500;
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout));
//setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout, sizeof(timeout));
int bytesReceived = recv(sock, buf, 1024, 0);
if (bytesReceived > 0) {
//Check to see if it equals one of the strings above
if (strstr(pbuf, CreateAccount)) {
//Run program to create account
int accountSuccess;
accountSuccess = accountCreation(sock);
if (accountSuccess == 0) {
int sendResult = send(sock, accInfoSuccess.c_str(), accInfoSuccess.size() + 1, 0);
}
else {
int sendResult = send(sock, accInfoProblem.c_str(), accInfoProblem.size() + 1, 0);
}
}
else if (strstr(pbuf, Settings)) {
int settingsSuccess;
settingsSuccess = settingsCreation(sock);
if (settingsSuccess == 0) {
int sendResult = send(sock, settingsInfoSuccess.c_str(), settingsInfoSuccess.size() + 1, 0);
}
else {
int sendResult = send(sock, settingsInfoProblem.c_str(), settingsInfoProblem.size() + 1, 0);
}
}
else if (strstr(pbuf, CheckStatus)) {
//Check to see if program that runs account is running
int accountSuccess = isRunning();
if (accountSuccess == 0) {
int sendResult = send(sock, accRun.c_str(), accRun.size() + 1, 0);
}
else if (accountSuccess == 1){
int sendResult = send(sock, accNoRun.c_str(), accNoRun.size() + 1, 0);
}
else {
int sendResult = send(sock, accNoInfo.c_str(), accNoInfo.size() + 1, 0);
}
}
else if (strstr(pbuf, Info)) {
//Read text file containing account info and send to server
int infoChecker = checkInfo(sock);
if (infoChecker != 0) {
int sendResult = send(sock, accNoInfo.c_str(), accNoInfo.size() + 1, 0);
}
}
else if (strstr(pbuf, Run)) {
//Runs the account running program
int running = runProg();
if (running == 0) {
int sendResult = send(sock, accRun.c_str(), accRun.size() + 1, 0);
}
else {
int sendResult = send(sock, accRunErr.c_str(), accRunErr.size() + 1, 0);
}
}
else if (strstr(pbuf, Kill)) {
//Kills this program
WSACleanup();
return 0;
}
else {
//Send back to server that the wrong thing was inputted
int sendResult = send(sock, TryAgain.c_str(), TryAgain.size() + 1, 0);
ZeroMemory(buf, 1024);
loopCounter = 0;
}
}
else {
//Check to make sure bot is running
int vroom = isRunning();
if (vroom == 1) {
//runProg();
loopCounter = 0;
}
else {
loopCounter = 0;
}
}
if (PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE) != 0) {
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
} while (loopCounter == 0);
WSACleanup();
return 0;
}
There are a TON of problems with the code shown, but lets start with the most important one that is affecting your message issue - all of that thread-blocking socket code DOES NOT belong inside your WinMain() at all, let alone inside your message loop itself. That is why your handling of window messages, like WM_POWERBROADCAST, is running so slow.
You need to restructure your code. Either:
move the socket code to a worker thread, and let it block that thread all it wants.
use asynchronous socket I/O (via WSAAsyncSelect(), etc) that you can process inside of your WindowProc. Or use overlapped I/O. Either way, no threading or blocking operations are needed.
Whatever you do, DO NOT block WinMain()'s message loop.
That being said, other problems with your code include:
SHGetKnownFolderPath(..., &UserProf); wcsncat(UserProf, EndProf, 23); is undefined behavior. SHGetKnownFolderPath() does not allocate enough memory for you to append anything onto. You need to allocate another buffer large enough to copy UserProf into and append EndProf into. Or, simply convert UserProf to a std::wstring first and then append EndProf onto the end of that (either way, don't forget to free UserProf when you are done with it - you are currently leaking it).
you should not be adding your custom UserUpdates subfolder directly to the user's AppData folder itself. Use FOLDERID_LocalAppData/Low, FOLDERID_RoamingAppData, or FOLDERID_ProgramData instead to get a more appropriate folder to add your things to.
string wstr(ws.begin(), ws.end()); is not the correct way to convert a std::wstring to a std::string. Use std::wstring_convert, WideCharToMultiByte(), or other similar conversion instead. Or, simply do not convert at all, use std::wcout and SetCurrentDirectoryW() instead.
you are misusing SO_REUSEADDR. It is useless after bind()/connect(), and you are not even enabling it properly anyway.
recv() does not return null-terminated data, like you are expecting. You are likely to experience undesired side effects, if not alright crashes, in your code that tries to match up received strings. TCP is stream oriented, not message oriented, like you think it is. There are numerous posts on StackOverflow that demonstrate the proper way to handle I/O over TCP.
With all of that said, try something more like this:
HWND hMyWnd = NULL;
HANDLE hThread = NULL;
bool stopThread = false;
int readString(SOCKET sock, char *buf, int buflen, string &str)
{
str.clear();
char ch, *pbuf = buf;
int len = 0, bytesReceived;
do {
if (stopThread)
return -2;
bytesReceived = recv(sock, &ch, 1, 0);
if (bytesReceived == -1) {
if ((WSAGetLastError() != WSAETIMEDOUT) || !str.empty()) {
//cerr << "Can't read from socket, Err#" << WSAGetLastError() << endl;
return -1;
}
return 1;
}
if (bytesReceived == 0) {
//cerr << "Socket disconnected by server" << endl;
return 0;
}
if (ch == '\0')
break;
*pbuf++ = ch;
len += bytesReceived;
if (len == buflen) {
str.append(buf, len);
pbuf = buf;
len = 0;
}
}
while (true);
if (len > 0)
str.append(buf, len);
return 1;
}
int sendString(SOCKET sock, const string &str)
{
const char *pbuf = str.c_str();
int len = str.length() + 1, bytesSent;
do {
if (stopThread)
return -2;
bytesSent = send(sock, pbuf, len, 0);
if (bytesSent == -1) {
//cerr << "Can't send to socket, Err#" << WSAGetLastError() << endl;
return -1;
}
pbuf += bytesSent;
len -= bytesSent;
}
while (len > 0);
return 1;
}
//Things to compare
const char* CreateAccount = "create"; //Server tells client to make IG account
const char* CheckStatus = "check"; //Client tells server if account is running or not
const char* Info = "info"; //Client sends Username and Password of account to server
const char* Run = "run"; //Tells client to start running the account
const char* Kill = "kill"; //Kills program on client for around a month
const char* Settings = "settings"; //Server sets settings for account to run on
//Things to send
const string TryAgain = "#13 Not a valid input, either type [check] to check if the account is running, type [create] to create new account, or type [info] for account information\n";
const string accInfoSuccess = "#777 You have successfully entered the information for the account (^.^)\n";
const string settingsInfoSuccess = "#777 You have successfully set the settings for this account (^.^)\n";
const string accInfoProblem = "#13 There was a problem in either saving the information to this account or the account creation program. Type [create] and try again (T.T)\n";
const string settingsInfoProblem = "#13 There was a problem in saving the account settings. Type [settings] and try again (T.T)\n";
const string accRun = "#777 The account is currently running! ~(^.^)~\n";
const string accNoRun = "#13 Sorry the account isn't running, type [run] to run the account (O.o)\n";
const string accNoInfo = "#13 There is no info for an account that can be run. Type [create] to make information (\".\")\n";
const string accRunErr = "#13 There is a problem with opening the main bot program, try again. If this problem persists, there is an issue clientside V(T.T)V\n";
DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
string ipAddress = "10.0.0.201"; //IP address of my computer on local network
int port = 13777;
WSAData data;
WORD ver = MAKEWORD(2, 2);
int wsResult = WSAStartup(ver, &data);
if (wsResult != 0) {
//cerr << "Can't start Winsock, Err#" << wsResult << endl;
return 0;
}
sockaddr_in hint = {};
hint.sin_family = AF_INET;
hint.sin_port = htons(port);
inet_pton(AF_INET, ipAddress.c_str(), &hint.sin_addr);
SOCKET sock = INVALID_SOCKET;
char buf[1024]; //Where message from server will be stored
string str;
while (!stopThread) {
//attempt to connect to server
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == INVALID_SOCKET) {
//cerr << "Can't create socket, Err#" << WSAGetLastError() << endl;
break;
}
//BOOL on = TRUE;
//setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof(on));
//u_long block = 0;
//ioctlsocket(sock, FIONBIO, &block);
DWORD timeout = 500;
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout));
//setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout, sizeof(timeout));
wsResult = connect(sock, (sockaddr*)&hint, sizeof(hint));
if (wsResult != SOCKET_ERROR) {
do {
wsResult = readString(sock, buf, sizeof(buf), str);
if (wsResult <= 0)
break;
if (!str.empty()) {
//Check to see if it equals one of the strings above
if (str == CreateAccount) {
//Run program to create account
if (accountCreation(sock) == 0) {
wsResult = sendString(sock, accInfoSuccess);
}
else {
wsResult = sendString(sock, accInfoProblem);
}
}
else if (str == Settings) {
if (settingsCreation(sock) == 0) {
wsResult = sendString(sock, settingsInfoSuccess);
}
else {
wsResult = sendString(sock, settingsInfoProblem);
}
}
else if (str == CheckStatus) {
//Check to see if program that runs account is running
int accountSuccess = isRunning();
if (accountSuccess == 0) {
wsResult = sendString(sock, accRun);
}
else if (accountSuccess == 1){
wsResult = sendString(sock, accNoRun);
}
else {
wsResult = sendString(sock, accNoInfo);
}
}
else if (str == Info) {
//Read text file containing account info and send to server
if (checkInfo(sock) != 0) {
wsResult = sendString(sock, accNoInfo);
}
}
else if (str == Run) {
//Runs the account running program
if (runProg() == 0) {
wsResult = sendString(sock, accRun);
}
else {
wsResult = sendString(sock, accRunErr);
}
}
else if (str == Kill) {
//Kills this program
PostMessage(hMyWnd, WM_CLOSE, 0, 0);
stopThread = true;
break;
}
else {
//Send back to server that the wrong thing was inputted
wsResult = sendString(sock, TryAgain);
}
}
else {
//Check to make sure bot is running
if (isRunning() == 1) {
//runProg();
}
}
}
while (!stopThread);
}
closesocket(sock);
sock = INVALID_SOCKET;
if (!stopThread)
Sleep(5000);
}
WSACleanup();
return 0;
}
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
switch (message) {
case WM_CREATE: {
hThread = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);
return 0;
case WM_POWERBROADCAST:
DestroyWindow(hWnd);
return 0;
case WM_DESTROY:
if (hThread) {
stopThread = true;
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
hThread = NULL;
}
PostQuitMessage(0);
return 0;
case WM_CLOSE:
DestroyWindow(hWnd);
return 0;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
//Change the current directory of the program back to the appropriate folder
wchar_t* UserProf;
if (SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, NULL, &UserProf) == S_OK) {
wstring wstr = wstring(UserProf) + L"\\UserUpdates";
//wcout << wstr << endl;
SetCurrentDirectoryW(wstr.c_str());
CoTaskMemFree(UserProf);
}
WNDCLASSW WindowClass{CS_NOCLOSE, WindowProc, 0, 0, hInstance, NULL, LoadCursor(nullptr, IDC_ARROW), NULL, NULL, L"chakra"};
if (!RegisterClassW(&WindowClass)) {
//cerr << "Can't register window class, Err#" << GetLastError() << endl;
return 0;
}
hMyWnd = CreateWindowW(L"chakra", L"star", WS_POPUP, 0, 0, 10, 10, NULL, NULL, hInstance, NULL);
if (!hMyWnd) {
//cerr << "Can't create window, Err#" << GetLastError() << endl;
return 0;
}
ShowWindow(hMyWnd, SW_HIDE);
MSG Msg;
while (GetMessage(&Msg, NULL, 0, 0)) {
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return 0;
}
#include "create.h"
std::mutex acceptMutex;
namespace kojang{
CreateServer::CreateServer()
{
init();
}
void CreateServer::showError(const char * msg)
{
std::cout << "에러 : " << msg << std::endl;
exit(-1);
}
void CreateServer::init()
{
WSAStartup(MAKEWORD(2, 2), &wsa);
server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (server == INVALID_SOCKET)
showError("서버 생성 실패");
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("192.168.0.2");
addr.sin_port = htons(23000);
if (bind(server, (sockaddr *)&addr, sizeof(addr)) == SOCKET_ERROR)
showError("바인딩 실패");
if (listen(server, SOMAXCONN) == SOCKET_ERROR)
showError("듣기 실패");
}
void CreateServer::Accept()
{
while (true)
{
std::cout << "클라이언트 접속 대기중.... " << std::endl;
c_size = sizeof(c_addr);
acceptMutex.lock();
client = accept(server, (SOCKADDR*)&c_addr, &c_size);
if (client == INVALID_SOCKET)
{
std::cerr << "error" << std::endl;
acceptMutex.unlock();
continue;
}
v.emplace_back(client);
acceptMutex.unlock();
std::thread t1 = std::thread([this]{ this->run_r(&client);});
t1.detach();
}
}
void CreateServer::run_r(void* client)
{
rcv_msg(client);
}
void CreateServer::rcv_msg(void* data)
{
SOCKET* cl = (SOCKET*)data;
int len;
char message[500];
while ((len = recv(*cl, message, sizeof(message) - 1, 0)) != -1)
{
std::cout << len <<" byte" << std::endl;
std::for_each(v.begin(), v.end(), [&len, &message, &cl](SOCKET sock){ send(sock, message, len, 0); });
}
}
}
thread will be created when client connect server
but if 3 client connnect server ,last client's thread is running well but first,second client's thread did not run;
You're passing a pointer to the same socket (&client) to all the threads, so all threads are using the same one.
You should pass client instead.
std::thread t1 = std::thread([this]{ this->run_r((void*)client);});
// ...
void CreateServer::rcv_msg(void* data)
{
SOCKET cl = (SOCKET)data;
int len;
char message[500];
while ((len = recv(cl, message, sizeof(message) - 1, 0)) != -1)
// ...
void CreateServer::Accept()
{
while (true)
{
std::cout << "클라이언트 접속 대기중.... " << std::endl;
c_size = sizeof(c_addr);
acceptMutex.lock();
SOCKET client = accept(server, (SOCKADDR*)&c_addr, &c_size);
if (client == INVALID_SOCKET)
{
std::cerr << "error" << std::endl;
acceptMutex.unlock();
continue;
}
v.emplace_back(client);
acceptMutex.unlock();
std::thread t1 = std::thread([this,client]{ this->run_r((void*)&client);});
t1.detach();
}
}
i just change my code like this
thank you for everyone
i used same socket in different thread
I am having a lot of trouble tracking down where I am getting a BufferOverrun in the code below when I send it socket data from my flash/as3 telnet client. I am mostly looking to find more memory leaks and such, so in addition to this problem, is there an easier way to check for buffer overflow/overrun than manual debugging?
/*
MTSocketServer
--------------
The purpose of this application is to have a client application that can connect to this server.
This server should be able to parse messages from connected users and to send them to other users.
*/
// Headers and Namespace
#include "stdafx.h"
#include "MTSocketServer.h"
using namespace std;
// Constants
#define BUFFERSIZE 1000
#define PORT 20248
// Global Variables
SOCKET server;
struct Client_Data
{
SOCKET client_socket;
string user_id;
};
list<Client_Data> clients;
// Method Prototypes
UINT Server_Thread(LPVOID pParams);
UINT Client_Thread(LPVOID pParams);
string Recv_String(SOCKET listener);
void Send_String(const char* message, SOCKET sender);
bool Identity_Exists(string id);
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
AfxBeginThread(Server_Thread, NULL);
while(_getch() != 27);
closesocket(server);
WSACleanup();
return 0;
}
UINT Server_Thread(LPVOID pParams)
{
// Spawn Server Thread
cout << "Main thread spawned, press ESC at any time to exit.\r\n";
WSADATA wsa_data;
SOCKADDR_IN server_location;
if (int wsa_return_val = WSAStartup(0x101, &wsa_data) != 0)
{
cout << "Incorrect version of 'Ws2_32.dll'.\r\n";
cout << "Client thread de-initialized.\r\n";
AfxEndThread(0, true);
return 1;
}
server_location.sin_family = AF_INET;
server_location.sin_addr.s_addr = INADDR_ANY;
server_location.sin_port = htons(20248);
server = socket(AF_INET, SOCK_STREAM, NULL);
if (server == INVALID_SOCKET)
{
cout << "Socket creation error.\r\n";
cout << "Client thread de-initialized.\r\n";
AfxEndThread(0, true);
return 1;
}
if (bind(server, (SOCKADDR*)&server_location, sizeof(server_location)) != 0)
{
cout << "Socket binding error.\r\n";
cout << "Client thread de-initialized.\r\n";
AfxEndThread(0, true);
return 1;
}
if (listen(server, 10) != 0)
{
cout << "Socket listening error.\r\n";
cout << "Client thread de-initialized.\r\n";
AfxEndThread(0, true);
return 1;
}
SOCKET client;
SOCKADDR_IN client_location;
int len_of_client = sizeof(client_location);
bool abort = false;
while(abort == false)
{
client = accept(server, (SOCKADDR*)&client_location, &len_of_client);
// Spawn Client Thread
cout << "Connection from " << inet_ntoa(client_location.sin_addr) << ". Client thread spawned.\r\n";
AfxBeginThread(Client_Thread, (LPVOID)client);
}
// De-Initialize Server Thread
cout << "Server thread de-initialized.\r\n";
AfxEndThread(0, true);
return 0;
}
UINT Client_Thread(LPVOID pParams)
{
SOCKET client = (SOCKET)pParams;
string client_id = "";
// Check if a client with the same ID is on already
send(client, "ID_ME", 6, 0);
client_id = Recv_String(client);
if (Identity_Exists(client_id))
{
Send_String("That ID is already taken. Please try another.", client);
} else
{
cout << "Created ID " << client_id << " successfully\r\n";
Send_String("Type 'send' to send a message, 'quit' to exit.", client);
Client_Data this_client;
this_client.user_id = client_id;
this_client.client_socket = client;
clients.push_back(this_client);
bool is_con = true;
while(is_con)
{
string response = Recv_String(client);
if (response == "send")
{
Send_String("What username to send to?", client);
string to_id = Recv_String(client);
if (Identity_Exists(to_id))
{
Send_String("Type your message below: ", client);
string temp = Recv_String(client) + "\n\0";
const char* message = temp.c_str();
for (list<Client_Data>::iterator iterator = clients.begin(), end = clients.end(); iterator != end; ++iterator)
{
if (to_id == iterator->user_id)
{
SOCKET temp = iterator->client_socket;
cout << temp;
Send_String(message, temp);
}
}
} else
{
Send_String("Invalid username specified", client);
}
}
else if (response == "quit")
{
Send_String("Quit Command Issued", client);
break;
}
else
{
Send_String("Invalid Command Issued", client);
}
}
}
// De-Initialize Client Thread
closesocket(client);
cout << "Client thread de-initialized.\r\n";
AfxEndThread(0, true);
return 0;
}
// Function to parse full string values since they are often recieved one at a time
string Recv_String(SOCKET listener)
{
char buffer[BUFFERSIZE];
string temp;
int numofbytes = 0;
while (true)
{
int num = recv(listener, buffer, BUFFERSIZE, 0);
numofbytes++;
buffer[num] = '\0';
if (buffer[num-1] == '\n')
break;
if(numofbytes >= BUFFERSIZE-1)
break;
temp += buffer;
strcpy(buffer, "");
}
return temp;
}
void Send_String(const char* message, SOCKET sender)
{
char buffer[BUFFERSIZE];
strcpy(buffer, message);
size_t size = strlen(message);
int sendtest = send(sender, buffer, size, 0);
strcpy(buffer, "");
}
bool Identity_Exists(string id)
{
for (list<Client_Data>::iterator iterator = clients.begin(), end = clients.end(); iterator != end; ++iterator)
{
if (id == iterator->user_id)
{
return true;
}
}
return false;
}
buffer[num] = '\0'; writes one beyond the buffer if num happens to be equal to BUFFERSIZE. It writes one below the buffer if num happens to be -1.
if (buffer[num-1] == '\n') though not a buffer overrun, is also wrong. The \n can be anywhere (from 0 to n-1) in the buffer.