I am newbie in programming world. I am trying to make Login system with C++ so I try to connect MySQL database with my server program. without using socket I can connect with database well. But my Final Goal is to success login to my local server and add information to my DB.
I found that if I add "driver.h" from MySQL Connector 8.0, It said the connection is gone. actually it cant connect to socket. but when I comment out the "driver.h" hearder, It connect to socket well. but without "driver.h", I cant connect to my DB.
What is the problem and How can I solve it? the version of VS is 2022, and MySQL version is 8.0.30. Below is my full Code of Client and Server.
And sorry I cant emebed image still I am newbie here
[So I post in Notion][1]:https://sunny-green-970.notion.site/Error-ea96fbef0ea64e1bb1fd966699657547
Client
#define _CRT_SECURE_NO_WARNINGS
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <stdio.h>
#include <WinSock2.h>
#include <iostream>
#pragma comment(lib, "ws2_32.lib")
int main()
{
WSAData wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
SOCKET ServerSocket = socket(AF_INET, SOCK_STREAM, 0);
SOCKADDR_IN ServerAddrIn;
memset(&ServerAddrIn, 0, sizeof(SOCKADDR_IN));
ServerAddrIn.sin_family = PF_INET;
ServerAddrIn.sin_addr.s_addr = inet_addr("127.0.0.1");
ServerAddrIn.sin_port = htons(1234);
printf("client\n");
if (connect(ServerSocket, (SOCKADDR*)&ServerAddrIn, sizeof(SOCKADDR_IN)) == SOCKET_ERROR) // 자기 ip와 port 필요없다. 서버에 접속하면 된다.
{
std::cout << "Connect Failed." << std::endl;
exit(-1);
}
int Numnber = 0;
int WinCount = 0;
int TotalGamePlay = 0;
//connect(ServerSocket, (SOCKADDR*)&ServerAddrIn, sizeof(SOCKADDR_IN));
printf("Please Type Number: ");
scanf("%d", &Numnber);
printf("Please Type WinCount: ");
scanf("%d", &WinCount);
printf("Please Type TotalGamePlay: ");
scanf("%d", &TotalGamePlay);
char Buffer[1024] = { 0, };
memcpy(Buffer, &Numnber, 4);
memcpy(&Buffer[4], &WinCount, 4);
memcpy(&Buffer[8], &TotalGamePlay, 4);
int SentLength = send(ServerSocket, Buffer, 12, 0);
printf("Sent Length : %d\n", SentLength);
if (SentLength == 0)
{
//연결 종료s
std::cout << "Disconnected Client." << std::endl;
}
else if (SentLength < 0)
{
//Error
std::cout << "Disconnected Client By Error : " << GetLastError() << std::endl;
}
WSACleanup();
return 0;
}
Server
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <iostream>
#include <WinSock2.h>
#include <Windows.h>
#include "jdbc/mysql_connection.h"
#include "jdbc/cppconn/exception.h"
#include "jdbc/cppconn/resultset.h"
#include "jdbc/cppconn/statement.h"
#include "jdbc/cppconn/prepared_statement.h"
#include "jdbc/cppconn/driver.h"
#pragma comment(lib, "ws2_32.lib")
#ifdef _DEBUG
#pragma comment(lib, "debug/mysqlcppconn.lib")
#else
#pragma comment(lib, "mysqlcppconn.lib")
#endif
using namespace std;
std::string Utf8ToMultiByte(std::string utf8_str);
int main()
{
bool bRunning = true;
WSAData wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
SOCKET ServerSocket = socket(AF_INET, SOCK_STREAM, 0);
SOCKADDR_IN ServerAddrIn;
memset(&ServerAddrIn, 0, sizeof(SOCKADDR_IN));
ServerAddrIn.sin_family = AF_INET;
ServerAddrIn.sin_port = htons(1234);
ServerAddrIn.sin_addr.s_addr = htonl(INADDR_ANY);
fd_set Original;
fd_set CopyReads;
timeval Timeout;
Timeout.tv_sec = 0;
Timeout.tv_usec = 10;
FD_ZERO(&Original);
FD_SET(ServerSocket, &Original);
bind(ServerSocket, (SOCKADDR*)&ServerAddrIn, sizeof(SOCKADDR_IN));
listen(ServerSocket, 0);
printf("Server\n");
while (bRunning)
{
CopyReads = Original;
//polling
int fd_num = select(0, &CopyReads, 0, 0, &Timeout);
if (fd_num == 0)
{
continue;
}
if (fd_num == SOCKET_ERROR)
{
bRunning = false;
break;
}
for (size_t i = 0; i < Original.fd_count; ++i)
{
//등록한 소켓 리스트 중에 이벤트 발생 했음
if (FD_ISSET(Original.fd_array[i], &CopyReads))
{
if (Original.fd_array[i] == ServerSocket)
{
//서버 소켓에 이벤트가 발생함, 연결 요청
SOCKADDR_IN ClientSockAddrIn;
memset((char*)&ClientSockAddrIn, 0, sizeof(SOCKADDR_IN));
int ClientSockAddrInSize = sizeof(SOCKADDR_IN);
SOCKET ClientSocket = accept(ServerSocket, (SOCKADDR*)&ClientSockAddrIn, &ClientSockAddrInSize);
FD_SET(ClientSocket, &Original);
std::cout << "Connected client : " << ClientSocket << std::endl;
}
else
{
SOCKET ClientSocket = Original.fd_array[i];
//Client 소켓, Recv, Send
char Buffer[1024] = { 0, };
//blocking, non blocking
//packet 설계, protocol
int RecvLength = recv(ClientSocket, Buffer, sizeof(Buffer), 0);
if (RecvLength == 0)
{
//연결 종료
std::cout << "Disconnected Client." << std::endl;
FD_CLR(ClientSocket, &Original);
closesocket(ClientSocket);
}
else if (RecvLength < 0)
{
//Error
std::cout << "Disconnected Client By Error : " << GetLastError() << std::endl;
FD_CLR(ClientSocket, &Original);
closesocket(ClientSocket);
}
else
{
//자료가 있으면 처리
//packet parse
int number = 0;
int wincount = 0;
int totalgameplay = 0;
memcpy(&number, &buffer[0], 4);
memcpy(&wincount, &buffer[4], 4);
memcpy(&totalgameplay, &buffer[8], 4);
try
{
sql::driver* driver; //workbench
sql::connection* connection; //접속
sql::statement* statement; //query
sql::resultset* resultset; //결과화면
sql::preparedstatement* preparedstatement;
//work벤치 켜기
driver = get_driver_instance();
//연결 버튼 누르기
connection = driver->connect("tcp://127.0.0.1:3306", "root", "secret");
if (connection == nullptr)
{
cout << "connect failed" << endl;
exit(-1);
}
사용 데이터베이스 선정(use)
connection->setschema("logindata");
preparedstatement = connection->preparestatement("insert into new_table(number, wincount, totalgameplay) values( ?, ? ,?)");
preparedstatement->setint(1, number);
preparedstatement->setint(2, wincount);
preparedstatement->setint(3, totalgameplay);
preparedstatement->executeupdate();
statement = connection->createstatement();
resultset = statement->executequery("select * from new_table ");
for (;resultset->next();)
{
cout << resultset->getint("number") << " : " <<
utf8tomultibyte(resultset->getstring("wincount")) << " : " <<
utf8tomultibyte(resultset->getstring("totalgameplay")) << endl;
}
delete resultset;
delete preparedstatement;
delete connection;
}
catch (sql::sqlexception e)
{
cout << "# err: sqlexception in " << __file__;
cout << "(" << __function__ << ") on line " << __line__ << endl;
cout << "# err: " << e.what();
cout << " (mysql error code: " << e.geterrorcode();
cout << ", sqlstate: " << e.getsqlstate() << " )" << endl;
}
/*for (size_t i = 0; i < original.fd_count; ++i)
{
if (original.fd_array[i] != serversocket)
{
std::cout << original.fd_array[i] << std::endl;
int sentlength = send(original.fd_array[i], buffer, 8, 0);
}
}*/
}
}
}
}
}
closesocket(ServerSocket);
WSACleanup();
return 0;
}
std::string Utf8ToMultiByte(std::string utf8_str)
{
std::string resultString; char* pszIn = new char[utf8_str.length() + 1];
strncpy_s(pszIn, utf8_str.length() + 1, utf8_str.c_str(), utf8_str.length());
int nLenOfUni = 0, nLenOfANSI = 0; wchar_t* uni_wchar = NULL;
char* pszOut = NULL;
// 1. utf8 Length
if ((nLenOfUni = MultiByteToWideChar(CP_UTF8, 0, pszIn, (int)strlen(pszIn), NULL, 0)) <= 0)
return nullptr;
uni_wchar = new wchar_t[nLenOfUni + 1];
memset(uni_wchar, 0x00, sizeof(wchar_t) * (nLenOfUni + 1));
// 2. utf8 --> unicode
nLenOfUni = MultiByteToWideChar(CP_UTF8, 0, pszIn, (int)strlen(pszIn), uni_wchar, nLenOfUni);
// 3. ANSI(multibyte) Length
if ((nLenOfANSI = WideCharToMultiByte(CP_ACP, 0, uni_wchar, nLenOfUni, NULL, 0, NULL, NULL)) <= 0)
{
delete[] uni_wchar; return 0;
}
pszOut = new char[nLenOfANSI + 1];
memset(pszOut, 0x00, sizeof(char) * (nLenOfANSI + 1));
// 4. unicode --> ANSI(multibyte)
nLenOfANSI = WideCharToMultiByte(CP_ACP, 0, uni_wchar, nLenOfUni, pszOut, nLenOfANSI, NULL, NULL);
pszOut[nLenOfANSI] = 0;
resultString = pszOut;
delete[] uni_wchar;
delete[] pszOut;
return resultString;
}
[1]: https://sunny-green-970.notion.site/Error-ea96fbef0ea64e1bb1fd966699657547
[2]: https://i.stack.imgur.com/VK8m0.png
Related
A third question in the saga: How to correctly implement select to correctly get data from stdin and recv(). I recommend reading this and the other question it links to understand the situation.
Basically, I tried my luck at implementing select() myself. My code:
#include <iostream>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/select.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <cstring>
#include <stdlib.h>
using namespace std;
int main (int argc, char** argv) {
if (argv[1] == NULL) {
cout << "\033[31mTARGET NOT SPECIFIED - TERMINATING...\033[0m\n";
return -1;
}
if (argv[2] == NULL) {
cout << "\033[31mPORT NOT SPECIFIED - TERMINATING...\033[0m\n";
return -2;
}
string target = argv[1];
int port = atoi(argv[2]);
cout << "GENERATING SOCKET...\n";
int chatter = socket(AF_INET, SOCK_STREAM, 0);
if (chatter == -1) {
cout << "\033[31mSOCKET GENERATION FAILURE - TERMINATING...\033[0m\n";
return -3;
}
cout << "\033[32mSUCCESSFULLY GENERATED SOCKET\033[0m\n";
struct sockaddr_in hint;
hint.sin_family = AF_INET;
hint.sin_port = htons(port);
inet_pton(AF_INET, target.c_str(), &hint.sin_addr);
struct timeval tv;
tv.tv_usec = 0.0;
tv.tv_sec = 5;
int recval;
cout << "CONNECTING TO " << target << " AT PORT " << port << "...\n";
int connection_status = connect(chatter, (sockaddr*)&hint, sizeof(hint));
if (connection_status == -1) {
cout << "\033[31mCONNECTION FAILURE - TERMINATING...\033[0m\n";
return -4;
}
cout << "\033[32mCONNECTED TO HOST\033[0m\n";
char buf[4096] = {0};
string msg;
while (true) {
fd_set rfds;
FD_ZERO(&rfds);
FD_SET(chatter, &rfds);
getline(cin, msg);
msg+"\r\n";
int sendmsg = send(chatter, msg.c_str(), msg.size()+1, 0);
if (sendmsg == -1) {
cout << "\033[31mMESSAGE SENDING FAILURE - TERMINATING...\033[0m\n";
return -5;
}
recval = select(chatter + 1, &rfds, NULL, NULL, &tv);
switch(recval) {
case(0):
cout << "\033[31mTIMEOUT\033[0m\n";
break;
case(-1):
cout << "\033[31mERROR\033[0m\n";
break;
default:
if (recv(chatter, buf, 4096, 0) < 0) {
cout << "\033[31mFAILURE TO RECEIVE MESSAGE - TERMINATING...\033[0m\n";
return -6;
} else {
cout << recv(chatter, buf, 4096, 0) << "\n";
cout << buf << "\n";
}
break;
}
}
close(chatter);
return 0;
}
I keep getting TIMEOUT when trying the program on scanme.nmap.org and my HTTP server. What am I doing wrong?
At this point, after fixing something a user in the first question pointed out, I know that there isn't an issue with how I'm sending data. Just an issue with the way the program handles getting data from getline()/recv().
EDIT: NEW, IMPROVED, WORKING CODE THANKS TO ANSWERER
#include <iostream>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/select.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <cstring>
#include <stdlib.h>
using namespace std;
int main (int argc, char** argv) {
if (argv[1] == NULL) {
cout << "\033[31mTARGET NOT SPECIFIED - TERMINATING...\033[0m\n";
return -1;
}
if (argv[2] == NULL) {
cout << "\033[31mPORT NOT SPECIFIED - TERMINATING...\033[0m\n";
return -2;
}
string target = argv[1];
int port = atoi(argv[2]);
cout << "GENERATING SOCKET...\n";
int chatter = socket(AF_INET, SOCK_STREAM, 0);
if (chatter == -1) {
cout << "\033[31mSOCKET GENERATION FAILURE - TERMINATING...\033[0m\n";
return -3;
}
cout << "\033[32mSUCCESSFULLY GENERATED SOCKET\033[0m\n";
struct sockaddr_in hint;
hint.sin_family = AF_INET;
hint.sin_port = htons(port);
inet_pton(AF_INET, target.c_str(), &hint.sin_addr);
int recval;
cout << "CONNECTING TO " << target << " AT PORT " << port << "...\n";
int connection_status = connect(chatter, (sockaddr*)&hint, sizeof(hint));
if (connection_status == -1) {
cout << "\033[31mCONNECTION FAILURE - TERMINATING...\033[0m\n";
return -4;
}
cout << "\033[32mCONNECTED TO HOST\033[0m\n";
char buf[4096] = {0};
string msg;
while (true) {
struct timeval tv;
tv.tv_usec = 0.0;
tv.tv_sec = 5;
fd_set rfds;
FD_ZERO(&rfds);
FD_SET(chatter, &rfds);
getline(cin, msg);
msg += "\r\n";
const char *pMsg = msg.c_str();
size_t msgSize = msg.size();
do {
int numSent = send(chatter, pMsg, msgSize, 0);
if (numSent == -1) {
cout << "\033[31mMESSAGE SENDING FAILURE - TERMINATING...\033[0m\n";
close(chatter);
return -5;
}
pMsg += numSent;
msgSize -= numSent;
} while (msgSize > 0);
recval = select(chatter + 1, &rfds, NULL, NULL, &tv);
switch(recval) {
case(0):
cout << "\033[31mTIMEOUT\033[0m\n";
break;
case(-1):
cout << "\033[31mERROR\033[0m\n";
break;
default:
int numRead = recv(chatter, buf, 4096, 0);
if (numRead < 0) {
cout << "\033[31mFAILURE TO RECEIVE MESSAGE - TERMINATING...\033[0m\n";
close(chatter);
return -6;
}
else if (numRead == 0) {
cout << "\033[31mDISCONNECTED - TERMINATING...\033[0m\n";
close(chatter);
break;
} else {
cout << numRead << "\n";
cout.write(buf, numRead);
cout << "\n";
}
break;
}
}
close(chatter);
return 0;
}
On some platforms, select() alters the passed timeval to indicate how much time is remaining. So this is likely the cause of your timeout errors, as you are setting the timeval only once and it will eventually fall to 0. You need to reset your tv variable every time you call select(), so move that inside your while loop.
Also, you have 2 calls to recv() where you should be using only 1 call. You are ignoring the bytes received by the 1st recv(), and if the server happens to send less then 4096 bytes then there won't be any data left for the next call to select() to detect, unless the connection is disconnected.
Change this:
if (recv(chatter, buf, 4096, 0) < 0) {
cout << "\033[31mFAILURE TO RECEIVE MESSAGE - TERMINATING...\033[0m\n";
return -6;
} else {
cout << recv(chatter, buf, 4096, 0) << "\n";
cout << buf << "\n";
}
To this:
int numRead = recv(chatter, buf, 4096, 0);
if (numRead < 0) {
cout << "\033[31mFAILURE TO RECEIVE MESSAGE - TERMINATING...\033[0m\n";
return -6;
}
else if (numRead == 0) {
cout << "\033[32mHOST DISCONNECTED\033[0m\n";
break;
} else {
cout << numRead << "\n";
cout.write(buf, numRead);
cout << "\n";
}
Also, msg+"\r\n"; is a no-op, you probably meant to use msg += "\r\n"; instead.
And, you should not be including the msg's null terminator when calling send(). And you are not accounting for the possibility that send() may not be able to send the whole data in one go. You need to call send() in a loop instead, eg:
const char *pMsg = msg.c_str();
size_t msgSize = msg.size();
do {
int numSent = send(chatter, pMsg, msgSize, 0);
if (numSent == -1) {
cout << "\033[31mMESSAGE SENDING FAILURE - TERMINATING...\033[0m\n";
return -5;
}
pMsg += numSent;
msgSize -= numSent;
}
while (msgSize > 0);
I am writing for the first time in this language and could only write this
UDP server and client. I need help; I want to server waits for a response and displays it. If within 5 sec. the answer is not received, the program starts its execution again.If you don't understand task, you can translate task(fifth) :https://www.opennet.ru/docs/RUS/socket/node15.html
#include <iostream>
#include <WS2tcpip.h>
#pragma comment (lib, "ws2_32.lib")
using namespace std;
void main()
{
struct timeval tv;
fd_set fd;
WSADATA data;
WORD version = MAKEWORD(2, 2);
int wsOk = WSAStartup(version, &data);
cout << "Server opened" << endl;
if (wsOk != 0)
{
cout << "Can't start Winsock! " << wsOk;
return;
}
SOCKET in = socket(AF_INET, SOCK_DGRAM, 0);
sockaddr_in serverHint;
serverHint.sin_addr.S_un.S_addr = ADDR_ANY;
serverHint.sin_family = AF_INET;
serverHint.sin_port = htons(54000);
if (bind(in, (sockaddr*)& serverHint, sizeof(serverHint)) == SOCKET_ERROR)
{
cout << "Can't bind socket! " << WSAGetLastError() << endl;
return;
}
sockaddr_in client;
int clientLength = sizeof(client);
char buf[1024];
while (true)
{
FD_ZERO(&fd);
FD_SET(in, &fd);
tv.tv_sec = 5;
tv.tv_usec = 0;
if (select(0, &fd, NULL, NULL, &tv) > 0)
{
ZeroMemory(&client, clientLength);
ZeroMemory(buf, 1024);
int bytesIn = recvfrom(in, buf, 1024, 0, (sockaddr*)& client, &clientLength);
if (bytesIn == SOCKET_ERROR)
{
cout << "Error receiving from client " << WSAGetLastError() << endl;
continue;
}
char clientIp[256];
ZeroMemory(clientIp, 256);
inet_ntop(AF_INET, &client.sin_addr, clientIp, 256);
cout << "Message recv from " << clientIp << " : " << buf << endl;
}
else {
cout << "Timeout" << endl;
closesocket(in);
break;
}
closesocket(in);
WSACleanup();
}
}
Translation of the task by google translate:
Write a program that asks the user for an IP address, port number and text string,
sends a string to the specified address using the UDP protocol,
waits for a response, and displays it on the screen.
If within 5 sec. the answer is not received, the program starts its execution again.
Your program is completely missing part 1 and 2 so you must add those.
For part 3, move your current while loop so it covers everything in main:
int main() // note: main must be declared to return 'int'
{
while(true) { // new start of the while loop, first in main
// ... your current code until the below line ...
cout << "Message recv from " << clientIp << " : " << buf << endl;
// exit program if you've received a response
closesocket(in);
break; // break out of while loop
}
else {
cout << "Timeout" << endl;
}
closesocket(in);
WSACleanup();
} // end of while loop
WSACleanup();
} // end of main
This reinitializer Winsock2 for every try which is unnecessary and it also has closesocket in multiple places. I would add classes for both WSAStartup/WSACleanup and socket/closesocket to manage the resources they have acquire.
#include <iostream>
#include <WS2tcpip.h>
#pragma comment (lib, "ws2_32.lib")
using namespace std;
void main()
{
struct timeval tv;
fd_set fd;
WSADATA data;
WORD version = MAKEWORD(2, 2);
int wsOk = WSAStartup(version, &data);
cout << "5" << endl;
if (wsOk != 0)
{
cout << "Winsock" << wsOk;
return;
}
SOCKET in = socket(AF_INET, SOCK_DGRAM, 0);
sockaddr_in serverHint;
serverHint.sin_addr.S_un.S_addr = ADDR_ANY;
serverHint.sin_family = AF_INET;
serverHint.sin_port = htons(54000);
if (bind(in, (sockaddr*)& serverHint, sizeof(serverHint)) == SOCKET_ERROR)
{
cout << "hhhh" << WSAGetLastError() << endl;
return;
}
sockaddr_in client;
int clientLength = sizeof(client);
char buf[1024];
while (true)
{
FD_ZERO(&fd);
FD_SET(in, &fd);
tv.tv_sec = 5;
tv.tv_usec = 0;
if (select(0, &fd, NULL, NULL, &tv) > 0)
{
ZeroMemory(&client, clientLength);
ZeroMemory(buf, 1024);
int bytesIn = recvfrom(in, buf, 1024, 0, (sockaddr*)& client, &clientLength);
if (bytesIn == SOCKET_ERROR)
{
cout << "EEEROOR" << WSAGetLastError() << endl;
continue;
}
char clientIp[256];
ZeroMemory(clientIp, 256);
inet_ntop(AF_INET, &client.sin_addr, clientIp, 256);
cout << "С " << clientIp << " : " << buf << endl;
closesocket(in);
WSACleanup();
exit(0);
}
else {
cout << "jhkjhkjhjn" << endl;
closesocket(in);
main();
}
}
}
I'm trying to build a client and a server in the same program. For example, user 1 sends a packet of data to user 2, user 2 after receiving the packet sends back a different packet to user 1. The problem is, after running the program neither user receives the packets.If I build the client in a separate program from the server it works
#pragma comment(lib,"ws2_32.lib")
#include <WinSock2.h>
#include <iostream>
#include <thread>
static const int num_threads = 2;
static char buffer[8096 + 1];
char a[256] = {};
char MOTD[256];
void call_from_thread(int tid) {
// ---------- Server code: ---------- //
if( tid == 0 ){
WSAData wsaData;
WORD DllVersion = MAKEWORD(2, 1);
if (WSAStartup(DllVersion, &wsaData) != 0){MessageBoxA(NULL, "WinSock startup failed", "Error", MB_OK | MB_ICONERROR);}
SOCKADDR_IN addr;
int addrlen = sizeof(addr);
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
addr.sin_port = htons(1112);
addr.sin_family = AF_INET;
SOCKET sListen = socket(AF_INET, SOCK_STREAM, NULL);
bind(sListen, (SOCKADDR*)&addr, sizeof(addr));
listen(sListen, SOMAXCONN);
SOCKET newConnection;
newConnection = accept(sListen, (SOCKADDR*)&addr, &addrlen);
if (newConnection == 0){
std::cout << "Failed to accept the client's connection." << std::endl;
}else{
std::cout << "Client Connected!" << std::endl;
}
while (true){
std::cin >> a;
send(newConnection, a, sizeof(a), NULL);
}
}else if( tid == 1 ){
// ---------- Client code: ---------- //
WSAData wsaData;
WORD DllVersion = MAKEWORD(2, 1);
if (WSAStartup(DllVersion, &wsaData) != 0){MessageBoxA(NULL, "Winsock startup failed", "Error", MB_OK | MB_ICONERROR);}
SOCKADDR_IN addr;
int sizeofaddr = sizeof(addr);
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
addr.sin_port = htons(1111);
addr.sin_family = AF_INET;
SOCKET Connection = socket(AF_INET, SOCK_STREAM, NULL); //Set Connection socket
if (connect(Connection, (SOCKADDR*)&addr, sizeofaddr) != 0) //If we are unable to connect...
{
MessageBoxA(NULL, "Failed to Connect", "Error", MB_OK | MB_ICONERROR);
//return 0; //Failed to Connect
}
std::cout << "Connected!" << std::endl;
char MOTD[256];
while (true){
recv(Connection, MOTD, sizeof(MOTD), NULL); //Receive Message of the Day buffer into MOTD array
std::cout << "MOTD:" << MOTD << std::endl;
}
}
// ---------- Thread selection: ---------- //
int main() {
std::thread t[num_threads];
for (int i = 0; i < num_threads; ++i) {
t[i] = std::thread(call_from_thread, i);
}
for (int i = 0; i < num_threads; ++i) {
t[i].join();
}
}
The server is listening on port 1112, but the client is connecting to port 1111. This means the client and server cannot possibly be connected to each other at all, whether they are in the same application or not.
I also see a number of other problems with your code, including:
WSAStartup() should be called once at app startup, not per thread.
Neither thread quits cleanly if any WinSock function fails.
The client thread does not wait for the server thread to open its listening port before the client can then connect to it.
Potential buffer overflows.
Resource leaks.
A lack of decent error handling.
On the server side, you are completely ignoring errors reported by socket(), bind(), listen(), and send(), and you are not checking the return value of accept() correctly.
On the client side, you are completely ignoring errors reported by socket() and recv(). And, you are not ensuring the MOTD buffer is null-terminated before printing it to std::cout.
Try something more like this:
#include <winsock2.h>
#include <windows.h>
#pragma comment(lib,"ws2_32.lib")
#include <iostream>
#include <thread>
#include <string>
#include <cstdint>
#include <stdexcept>
#include <limits>
#include <algorithm>
// The below variables are used to let the client wait for the server
// port to be opened. If you don't want to use these, especially if the
// client and server are ever run on different machines, you can omit
// these and instead just have the client call connect() in a loop
// until successful...
//
#include <mutex>
#include <condition_variable>
#include <chrono>
static std::condition_variable server_cv;
static std::mutex server_mtx;
static bool server_is_listening = false;
//
static const int num_threads = 2;
static const u_short server_port = 1111;
class winsock_error : public std::runtime_error
{
public:
int errCode;
std::string funcName;
winsock_error(int errCode, const char *funcName) : std::runtime_error("WinSock error"), errCode(errCode), funcName(funcName) {}
};
void WinSockError(const char *funcName, int errCode = WSAGetLastError())
{
throw winsock_error(errCode, funcName);
}
class connection_closed : public std::runtime_error
{
public:
connection_closed() : std::runtime_error("Connection closed") {}
};
class socket_ptr
{
public:
socket_ptr(SOCKET s) : m_sckt(s) {}
socket_ptr(const socket_ptr &) = delete;
socket_ptr(socket_ptr &&src) : m_sckt(src.m_sckt) { src.m_sckt = INVALID_SOCKET; }
~socket_ptr() { if (m_sckt != INVALID_SOCKET) closesocket(m_sckt); }
socket_ptr& operator=(const socket_ptr &) = delete;
socket_ptr& operator=(socket_ptr &&rhs) { m_sckt = rhs.m_sckt; rhs.m_sckt = INVALID_SOCKET; return *this; }
operator SOCKET() { return m_sckt; }
bool operator!() const { return (m_sckt == INVALID_SOCKET); }
private:
SOCKET m_sckt;
}
template <typename T>
T LimitBufferSize(size_t size)
{
return (T) std::min(size, (size_t) std::numeric_limits<T>::max());
}
void sendRaw(SOCKET sckt, const void *buffer, size_t buflen)
{
const char *ptr = static_cast<const char*>(buffer);
while (buflen > 0)
{
int numToSend = LimitBufferSize<int>(buflen);
int numSent = ::send(sckt, ptr, numToSend, 0);
if (numSent == SOCKET_ERROR)
WinSockError("send");
ptr += numSent;
buflen -= numSent;
}
}
void recvRaw(SOCKET sckt, void *buffer, size_t buflen)
{
char *ptr = static_cast<char*>(buffer);
while (buflen > 0)
{
int numToRecv = LimitBufferSize<int>(buflen);
int numRecvd = ::recv(sckt, ptr, numToRecv, 0);
if (numRecvd == SOCKET_ERROR)
WinSockError("recv");
if (numRecvd == 0)
throw connection_closed();
ptr += numRecvd;
buflen -= numRecvd;
}
}
void sendStr(SOCKET sckt, const std::string &str)
{
uint32_t len = LimitBufferSize<uint32_t>(str.size());
uint32_t tmp = htonl(len);
sendRaw(sckt, &tmp, sizeof(tmp));
if (len > 0)
sendRaw(sckt, str.c_str(), len);
}
std::string recvStr(SOCKET sckt)
{
std::string str;
uint32_t len;
recvRaw(sckt, &len, sizeof(len));
len = ntohl(len);
if (len > 0)
{
str.resize(len);
recvRaw(sckt, &str[0], len);
}
return str;
}
void server_thread()
{
std::cout << "[Server] Starting ..." << std::endl;
try
{
socket_ptr sListen(::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
if (!sListen)
WinSockError("socket");
SOCKADDR_IN addr = {};
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = ::inet_addr("127.0.0.1");
addr.sin_port = ::htons(server_port);
int addrlen = sizeof(addr);
if (::bind(sListen, (SOCKADDR*)&addr, sizeof(addr)) == SOCKET_ERROR)
WinSockError("bind");
if (::listen(sListen, 1) == SOCKET_ERROR)
WinSockError("listen");
// this is optional...
{
std::unique_lock<std::mutex> lk(server_mtx);
server_is_listening = true;
}
server_cv.notify_all();
//
std::cout << "[Server] Listening for Client ..." << std::endl;
socket_ptr newConnection(::accept(sListen, (SOCKADDR*)&addr, &addrlen));
if (!newConnection)
WinSockError("accept");
std::cout << "[Server] Client Connected!" << std::endl;
try
{
std::string a;
while (std::cin >> a)
sendStr(newConnection, a);
}
catch (const connection_closed &)
{
}
catch (const winsock_error &e)
{
std::cerr << "[Server] Client error: " << e.errCode << " on WinSock function: " << e.funcName << std::endl;
}
std::cout << "[Server] Client Disconnected!" << std::endl;
}
catch (const winsock_error &e)
{
std::cerr << "[Server] Error: " << e.errCode << " on WinSock function: " << e.funcName << std::endl;
}
catch (const std::exception &e)
{
std::cerr << "[Server] Unexpected Error! " << e.what() << std::endl;
}
std::cout << "[Server] Stopped!" << std::endl;
}
void client_thread()
{
std::cout << "[Client] Starting ..." << std::endl;
try
{
// this is optional, could call connect() below in a loop instead...
std::cout << "[Client] Waiting for Server ..." << std::endl;
{
std::unique_lock<std::mutex> lk(server_mtx);
if (!server_cv.wait_for(lk, std::chrono::seconds(5), []{ return server_is_listening; }))
throw std::runtime_error("Server not listening after 5 seconds!");
}
//
socket_ptr sConnection(::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
if (!sConnection)
WinSockError("socket");
SOCKADDR_IN addr = {};
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = ::inet_addr("127.0.0.1");
addr.sin_port = ::htons(server_port);
if (::connect(sConnection, (SOCKADDR*)&addr, sizeof(addr)) == SOCKET_ERROR)
WinSockError("connect");
std::cout << "[Client] Connected!" << std::endl;
try
{
std::string MOTD;
while (true)
{
MOTD = recvStr(sConnection);
std::cout << "[Client] MOTD: " << MOTD << std::endl;
}
}
catch (const connection_closed &)
{
}
catch (const winsock_error &e)
{
std::cerr << "[Client] Server error: " << e.errCode << " on WinSock function: " << e.funcName << std::endl;
}
std::cout << "[Client] Disconnected!" << std::endl;
}
catch (const winsock_error &e)
{
std::cerr << "[Client] Error: " << e.errCode << " on WinSock function: " << e.funcName << std::endl;
}
catch (const std::exception &e)
{
std::cerr << "[Client] Unexpected Error! " << e.what() << std::endl;
}
std::cout << "[Client] Stopped!" << std::endl;
}
int main()
{
WSADATA wsaData;
int ret = ::WSAStartup(MAKEWORD(2, 1), &wsaData);
if (ret != 0)
{
std::cerr << "WinSock Startup failed with error: " << ret << std::endl;
return -1;
}
std::cout << "WinSock Startup successful" << std::endl;
std::thread t[num_threads];
t[0] = std::thread(server_thread);
t[1] = std::thread(client_thread);
for (int i = 0; i < num_threads; ++i) {
t[i].join();
}
::WSACleanup();
return 0;
}
// In server.cpp after connection has established
std::string input;
input.reserve(5);
std::cout << "Enter message to send: ";
std::cin.ignore(); // =====(1)=====
std::getline(std::cin, input);
std::cout << "Sending..." << std::endl;
auto len = input.length();
auto bytes_sent = send(newFD, input.data(), len, 0); // =====(2)=====
std::cout << "Input length : " << input.length() << std::endl
<< "Input bytes sent : " << bytes_sent << std::endl;
My aim is to use std::string instead of plain old char[fixed] in simple tcp client server program. So in server.cpp I have 2 doubts. So far my initial guesses are working as expected. I've marked them above in code.
cin.ignore() vs cin.clear() + cin.sync()
std::string.data() vs std::string.c_str()
Which should I use? I'm not even sure of the difference b/w any of these and I don't know if they're contributing to my problem.
// In client.cpp
std::string message;
message.reserve(5);
auto len = message.capacity();
auto bytes_recv = recv(sockFD, &message.front(), len - 1, 0); // =====(1)=====
message[len] = 0; // =====(2)=====
close(sockFD);
freeaddrinfo(res);
std::cout << "Bytes recieved :" << bytes_recv << std::endl;
std::cout << message.c_str() << std::endl; // =====(3)=====
And in client.cpp, everything goes wrong when I try to send bigger strings. But I probably know the cause, however solution is somewhat tricky to implement.
Am I doing right thing to pass &std::string.front() to write incoming data?
This is wrong, string class should manage this, right? However since I'm directly writing to &front(), I guess length won't get updated or I'm not sure what happens but data surely gets lost when outputting with std::cout << message;.
I'm doing this just because I'm directly writing to &front, still it produces garbage if somehow data returned is smaller than total length, probably because it cannot find terminating character at right place?
server.cpp
// compile as 'g++ server.cpp -o server.app -std=c++14'
// run as : './server.app 8080'
#include <iostream>
#include <string>
#include <cstring>
extern "C" {
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <netinet/in.h>
}
int main(int argc, char *argv[])
{
if(argc != 2) {
std::cerr << "Run program as 'program port'" << std::endl;
return -1;
}
auto &portNum = argv[1];
const unsigned int backLog = 5;
struct addrinfo hints, *res, *p;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
int gAddRes = getaddrinfo(NULL, portNum, &hints, &res);
if(gAddRes != 0) {
std::cerr << gai_strerror(gAddRes) << std::endl;
return -2;
}
std::cout << "Detecting addresses" << std::endl;
unsigned int numOfAddr = 0;
char ipStr[INET6_ADDRSTRLEN];
for(p = res; p != NULL; p = p->ai_next) {
void *addr;
std::string ipVer = "IPv0";
if(p->ai_family == AF_INET) {
ipVer = "IPv4";
struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr;
addr = &(ipv4->sin_addr);
++numOfAddr;
}
else {
ipVer = "IPv6";
struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr;
addr = &(ipv6->sin6_addr);
++numOfAddr;
}
inet_ntop(p->ai_family, addr, ipStr, sizeof(ipStr));
std::cout << "(" << numOfAddr << ") " << ipVer << " : " << ipStr
<< std::endl;
}
if(!numOfAddr) {
std::cerr << "Found no host address to use" << std::endl;
return -3;
}
std::cout << "Enter the number of host address to bind with:" << std::endl;
unsigned int choice = 0;
bool madeChoice = false;
do {
std::cin >> choice;
if(choice > (numOfAddr + 1) || choice < 1) {
madeChoice = false;
std::cout << "Wrong choice, try again!" << std::endl;
}
else
madeChoice = true;
} while(!madeChoice);
p = res;
bool isIPv4 = true;
if(choice > 1) {
unsigned int temp = 1;
while(choice < temp) {
p = p->ai_next;
++temp;
}
if(p->ai_family == AF_INET) {
isIPv4 = true;
}
else
isIPv4 = false;
}
int sockFD = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
if(sockFD == -1) {
std::cerr << "Error while creating socket" << std::endl;
freeaddrinfo(res);
return -4;
}
int bindR = bind(sockFD, p->ai_addr, p->ai_addrlen);
if(bindR == -1) {
std::cerr << "Error while binding socket" << std::endl;
close(sockFD);
freeaddrinfo(res);
return -5;
}
int listenR = listen(sockFD, backLog);
if(listenR == -1) {
std::cerr << "Error while Listening on socket" << std::endl;
close(sockFD);
freeaddrinfo(res);
return -6;
}
struct sockaddr_storage client_addr;
socklen_t client_addr_size = sizeof(client_addr);
int newFD =
accept(sockFD, (struct sockaddr *)&client_addr, &client_addr_size);
if(newFD == -1) {
std::cerr << "Error while Accepting on socket" << std::endl;
close(sockFD);
freeaddrinfo(res);
return -7;
}
std::string input;
input.reserve(5);
std::cout << "Enter message to send: ";
std::cin.ignore();
std::getline(std::cin, input);
std::cout << "Sending..." << std::endl;
auto len = input.length();
auto bytes_sent = send(newFD, input.data(), len, 0);
std::cout << "Input length : " << input.length() << std::endl
<< "Input bytes sent : " << bytes_sent << std::endl;
close(newFD);
close(sockFD);
freeaddrinfo(res);
return 0;
}
client.cpp
// compile as 'g++ client.cpp -o client.app -std=c++14'
// run as : './client.app 0 8080'
#include <iostream>
#include <cstring>
extern "C" {
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <netinet/in.h>
}
int main(int argc, char *argv[])
{
if(argc != 3) {
std::cerr << "Run program as 'program ipaddress port'" << std::endl;
return -1;
}
auto &ipAddress = argv[1];
auto &portNum = argv[2];
struct addrinfo hints, *res, *p;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
int gAddRes = getaddrinfo(ipAddress, portNum, &hints, &res);
if(gAddRes != 0) {
std::cerr << gai_strerror(gAddRes) << std::endl;
return -2;
}
std::cout << "Detecting addresses" << std::endl;
unsigned int numOfAddr = 0;
char ipStr[INET6_ADDRSTRLEN];
for(p = res; p != NULL; p = p->ai_next) {
void *addr;
std::string ipVer = "IPv0";
if(p->ai_family == AF_INET) {
ipVer = "IPv4";
struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr;
addr = &(ipv4->sin_addr);
++numOfAddr;
}
else {
ipVer = "IPv6";
struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr;
addr = &(ipv6->sin6_addr);
++numOfAddr;
}
inet_ntop(p->ai_family, addr, ipStr, sizeof(ipStr));
std::cout << "(" << numOfAddr << ") " << ipVer << " : " << ipStr
<< std::endl;
}
if(!numOfAddr) {
std::cerr << "Found no host address to use" << std::endl;
return -3;
}
std::cout << "Enter the number of host address to bind with:" << std::endl;
unsigned int choice = 0;
bool madeChoice = false;
do {
std::cin >> choice;
if(choice > (numOfAddr + 1) || choice < 1) {
madeChoice = false;
std::cout << "Wrong choice, try again!" << std::endl;
}
else
madeChoice = true;
} while(!madeChoice);
p = res;
bool isIPv4 = true;
if(choice > 1) {
unsigned int temp = 1;
while(choice < temp) {
p = p->ai_next;
++temp;
}
if(p->ai_family == AF_INET) {
isIPv4 = true;
}
else
isIPv4 = false;
}
int sockFD = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
if(sockFD == -1) {
std::cerr << "Error while creating socket" << std::endl;
return -4;
}
int connectR = connect(sockFD, p->ai_addr, p->ai_addrlen);
if(connectR == -1) {
close(sockFD);
std::cerr << "Error while connecting socket" << std::endl;
return -5;
}
std::string message;
message.reserve(5);
auto len = message.capacity();
auto bytes_recv = recv(sockFD, &message.front(), len - 1, 0);
message[len] = 0;
close(sockFD);
freeaddrinfo(res);
std::cout << "Bytes recieved :" << bytes_recv << std::endl;
std::cout << message.c_str() << std::endl;
return 0;
}
Your question on this is too vague to provide a helpful answer.
data() and c_str() are effectively the same thing since C++11. It doesn't matter which one you use. EDIT: In C++17, data() will have a non-const overload that returns a non-const char*, so you will not need to do &message.front() to access a modifiable form of the underlying buffer. c_str() will remain const.
&message.front() is right... and wrong. That is the way to get a non-const char* to the contents of your std::string. BUT message is uninitialized and has a size() of 0 at that point in the code, so I'm not even sure that line of code is well-defined behavior. Rather than doing a reserve(5) I would construct your string like this: auto message = std::string(5, ' '); Then when you pass it into recv there will actually be valid stuff there for it to overwrite and you'll be able to read it from message afterwards.
Yes, this is wrong. You should be setting your string up to be the actual size you need. I suspect you can just pass in len instead of len - 1 if you do this. On this topic, are you certain everything you'll ever receive is only 4 bytes long? Or are you intentionally only reading 4 bytes at a time?
a) you don't need to pass c_str() to std::cout. << is overloaded to accept std::string as well. b) recv returns the number of bytes that you received. If that value is less than the size you initialized your message to, then the remaining characters in your string will be garbage (or ' ' chars if you followed my advice re:#3). I would do message.resize(bytes_recv); after receiving the message.
Your questions have been addressed by caps,, but my 2 cents. What about having your own send/recv functions and hiding the complexity?
For example along the lines of:
ssize_t recv(int sockfd, std::string &buf, size_t len, int flags) {
buf.resize(len); // current status unknown -> make it fit
ssize_t n = ::recv(sockfd, (void *)buf.data(), len, flags);
buf.resize(n >= 0 ? n : 0); // take error into account
return n;
}
I'm trying to write a server for a client/server chat program.
The only problem is that if once client disconnects, the server starts spamming their last message to the server. Even if they reconnect, it keeps spamming..I've tried googling, but I can't find anything.
Here's the Server Code:
#include "MasterServer.h"
using namespace std;
SOCKADDR_IN Server;
int addrlen = sizeof(Server);
SOCKET sListen;
SOCKET Connect;
SOCKET* Connections;
int port = 444;
int ConCounter = 0;
char* Recv = new char[256];
int ServerThread(int ID)
{
ZeroMemory(Recv, sizeof(Recv));
for(;;)
{
if(recv(Connections[ID],Recv ,256 ,NULL))
{
cout << Recv << endl;
}
}
}
int InitWinSock()
{
int RetVal = 0;
WSAData wsa;
WORD Version = MAKEWORD(2,1);
RetVal = WSAStartup(Version, &wsa);
return RetVal;
}
int main()
{
int RetVal = 0;
RetVal = InitWinSock();
if(RetVal != 0)
{
cout << "WinSock Start Up Failure";
}
Connections = (SOCKET*)calloc(64, sizeof(SOCKET));
sListen = socket(AF_INET, SOCK_STREAM, NULL);
Connect = socket(AF_INET, SOCK_STREAM, NULL);
cout << "\t\t----====ModernBacon Server====----"<< endl;
cout << "What Port Would You Like To Run On [Default 444]: ";
cin >> port;
system("cls");
Server.sin_addr.s_addr = inet_addr("127.0.0.1");
Server.sin_family = AF_INET;
Server.sin_port = htons(port);
bind(sListen, (SOCKADDR*)&Server, sizeof(Server));
//Listening
listen(sListen, 64);
cout << "Listening For Connections IP:"<<inet_ntoa(Server.sin_addr);"Port:"<<port<<
endl;
for(;;)
{
if(Connect = accept(sListen, (SOCKADDR*)&Server, &addrlen))
{
Connections[ConCounter] = Connect;
char* ID = new char[64];
ZeroMemory(ID, sizeof(ID));
itoa(ConCounter, ID, 10);
send(Connections[ConCounter], ID, sizeof(ID),NULL);
ConCounter = ConCounter + 1;
CreateThread(NULL,NULL, (LPTHREAD_START_ROUTINE)
ServerThread, (LPVOID)(ConCounter -1), NULL, NULL);
cout << "\t\tClient Connected!\tID: " <<
ConCounter << endl;
}
}
return(0);
}
I have no clue whats going on...
There are quite a few problems with your code. Try something more like this instead:
#include "MasterServer.h"
#include <string>
using namespace std;
static const int MAX_CLIENTS = 64;
static const int MAX_RECV = 256;
struct ClientInfo
{
int ID;
SOCKET Connection;
char Recv[MAX_RECV];
};
ClientInfo Clients[MAX_CLIENTS];
DWORD WINAPI ServerThread(LPVOID lpParam)
{
ClientInfo *Client = (ClientInfo*) lpParam;
char szID[64] = {0};
itoa(Client->ID, szID, 10);
int RetVal = send(Client->Connection, szID, sizeof(szID), NULL);
if (RetVal != sizeof(szID))
{
cout << "Client " << Client->ID << " Send Failure. Error " << WSAGetLastError() << endl;
}
else
{
do
{
RetVal = recv(Client->Connection, Client->Recv, MAX_RECV, NULL);
if (RetVal == SOCKET_ERROR)
{
cout << "Client " << Client->ID << " Recv Failure. Error " << WSAGetLastError() << endl;
break;
}
if (RetVal == 0)
{
cout << "Client " << Client->ID << " disconnected" << endl;
break;
}
cout << "Client " << Client->ID << ": " << string(Client->Recv, RetVal) << endl;
}
while (true);
}
closesocket(Client->Connection);
Client->Connection = INVALID_SOCKET;
return 0;
}
int InitWinSock()
{
WSAData wsa;
return WSAStartup(MAKEWORD(2,1), &wsa);
}
int main()
{
SOCKADDR_IN addr;
int addrlen;
SOCKET sListen;
SOCKET sClient;
int port = 444;
int index;
cout << "\t\t----====ModernBacon Server====----"<< endl;
for (int i = 0; i < MAX_CLIENTS; ++i)
Connections[i] = INVALID_SOCKET;
int RetVal = InitWinSock();
if (RetVal != 0)
{
cout << "WinSock Start Up Failure. Error " << RetVal << endl;
return 0;
}
sListen = socket(AF_INET, SOCK_STREAM, NULL);
if (sListen == INVALID_SOCKET)
{
cout << "WinSock Socket Failure. Error " << WSAGetLastError() << endl;
return 0;
}
cout << "What Port Would You Like To Run On [Default 444]: ";
cin >> port;
system("cls");
ZeroMemory(&addr, sizeof(addr));
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
RetVal = bind(sListen, (SOCKADDR*)&addr, sizeof(addr));
if (RetVal != 0)
{
cout << "WinSock Bind Failure. Error " << WSAGetLastError() << endl;
return 0;
}
//Listening
RetVal = listen(sListen, MAX_CLIENTS);
if (RetVal != 0)
{
cout << "WinSock Listen Failure. Error " << WSAGetLastError() << endl;
return 0;
}
cout << "Listening For Connections. IP: " << inet_ntoa(addr.sin_addr) << ", Port: " << port << endl;
do
{
addrlen = sizeof(addr);
sClient = accept(sListen, (SOCKADDR*)&addr, &addrlen);
if (sClient == INVALID_SOCKET)
{
cout << "WinSock Accept Failure. Error " << WSAGetLastError() << endl;
return 0;
}
index = -1;
for (int i = 0; i < MAX_CLIENTS; ++i)
{
if (Clients[i].Connection == INVALID_SOCKET)
{
index = i;
break;
}
}
if (index == -1)
{
closesocket(sClient);
cout << "\t\tClient Connected. Max Clients Exceeded!" << endl;
continue;
}
Clients[index].ID = index + 1;
Clients[index].Connection = sClient;
CreateThread(NULL, NULL, &ServerThread, &Clients[index], NULL, NULL);
cout << "\t\tClient Connected!\tID: " << Clients[index].ID << endl;
}
while (true);
return 0;
}