Winsock - How to receive and send data simultaneously? - c++

I'm creating a simple chat client, where clients join the server and send messages to it, which then in turn sends those messages to all the other connected clients.
The issue I have is with figuring out how to have the clients be able to send messages to the server while also being able to simultaneously receive inbound messages from other clients via the server. The problem I run into is that any method I find of taking an input in, always makes the thread hang (as it's waiting for an input from the user).
This is true also for when listening for incoming data, but I've found a way to timeout the wait so I can loop it, and do things before seeing if there is any data needing to be processed again.
My client code:
int main()
{
WSADATA wsaData;
SOCKET ConnectionSocket = INVALID_SOCKET;
addrinfo *result = NULL;
addrinfo hints;
addrinfo *ptr = NULL;
fd_set set;
HANDLE hThread;
string username;
unsigned threadID;
int iResult;
int sent_msg;
int fileD;
char send_buffer[DEFAULT_BUFLEN];
char recieve_buffer[DEFAULT_BUFLEN];
bool connected = true;
int error_code;
timeval timeout_period;
/*
* Initalize WinSock.
*/
if (init_WinSock(wsaData)) { return 1; };
/*
* Zeroize structure.
*/
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
getaddrinfo("192.168.1.77", DEFAULT_PORT, &hints, &result);
ptr = result;
ConnectionSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
iResult = connect(ConnectionSocket, ptr->ai_addr, ptr->ai_addrlen);
freeaddrinfo(result);
if (iResult == SOCKET_ERROR) {
error_code = WSAGetLastError();
closesocket(ConnectionSocket);
cout << "Unable to connect!";
WSACleanup();
system("Pause >> null");
return 1;
}
cout << "Connected." << endl;
cout << "Please choose a username: ";
do {
cin.getline(send_buffer, (int)strlen(send_buffer));
if ((int)strlen(send_buffer) > 10) {
cout << "Name too long! Choose again: ";
memset(send_buffer, 0, DEFAULT_BUFLEN);
}
} while ((int)strlen(send_buffer) > 10);
username = send_buffer;
/*
* Initial connection. Send ID/username.
*/
send(ConnectionSocket, send_buffer, (int)strlen(send_buffer), 0);
memset(recieve_buffer, 0, DEFAULT_BUFLEN);
while (iResult != SOCKET_ERROR) {
FD_ZERO(&set); /* clear the set */
FD_SET(ConnectionSocket, &set);
FD_SET(0, &set);
error_code = select(ConnectionSocket + 1, &set, NULL, NULL, NULL);
error_code = WSAGetLastError();
if (FD_ISSET(0, &set)) {
cin.getline(send_buffer, DEFAULT_BUFLEN);
cout << username << ": " << send_buffer << endl;
send(ConnectionSocket, send_buffer, DEFAULT_BUFLEN, 0);
memset(send_buffer, 0, DEFAULT_BUFLEN);
} else if (FD_ISSET(ConnectionSocket, &set)) {
iResult = recv(ConnectionSocket, recieve_buffer, DEFAULT_BUFLEN, 0);
recieve_buffer[iResult] = '\0';
cout << "Placeholder: " << recieve_buffer << endl;
}
}
closesocket(ConnectionSocket);
cout << "\n\nDisconnected...";
system("pause >> null");
return 0;
}
Server code:
unsigned __stdcall handle_client(void *data)
{
client_socket_data_type client;
char recvbuf[DEFAULT_BUFLEN];
timeval timeout_period;
fd_set set;
int iResult;
// mutex mtx;
client = *((client_socket_data_type *)data);
memset(recvbuf, 0, DEFAULT_BUFLEN);
timeout_period.tv_sec = MAX_TIMEOUT;
timeout_period.tv_usec = 0;
FD_ZERO(&set); /* clear the set */
FD_SET(client.client_socket, &set);
iResult = select(client.client_socket, &set, NULL, NULL, &timeout_period);
while (iResult != SOCKET_ERROR) {
if (iResult > 0) {
recv(client.client_socket, recvbuf, DEFAULT_BUFLEN, 0);
if (recvbuf != " ") {
for each (SOCKET connected_clients in client.connected_clients)
{
if (client.client_socket != connected_clients) {
send(connected_clients, recvbuf, DEFAULT_BUFLEN, 0);
memset(recvbuf, 0, DEFAULT_BUFLEN);
}
}
}
}
iResult = select(client.client_socket, &set, NULL, NULL, &timeout_period);
}
clients--;
return 0;
}
int main()
{
WSADATA wsaData;
SOCKET listen_socket = INVALID_SOCKET;
SOCKET client_socket = INVALID_SOCKET;
struct addrinfo *result = NULL;
struct addrinfo hints;
client_socket_data_type client;
HANDLE hThread;
unsigned threadID;
char recv_buffer[DEFAULT_BUFLEN];
void *ctx;
int error_code;
int iResult;
/*
* Initalize WinSock.
*/
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed with error: %d\n", iResult);
return 1;
}
/*
* Zeroize structure.
*/
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);
if (iResult != 0) {
printf("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
return 1;
}
listen_socket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if (listen_socket == INVALID_SOCKET) {
printf("socket failed with error: %ld\n", WSAGetLastError());
freeaddrinfo(result);
WSACleanup();
return 1;
}
iResult = bind(listen_socket, result->ai_addr, (int)result->ai_addrlen);
if (iResult == SOCKET_ERROR) {
printf("bind failed with error: %d\n", WSAGetLastError());
freeaddrinfo(result);
closesocket(listen_socket);
WSACleanup();
return 1;
}
/*
* Finished setup. Clear structure.
*/
freeaddrinfo(result);
/*
* Listen on port for inbound connections.
*/
iResult = listen(listen_socket, SOMAXCONN);
if (iResult == SOCKET_ERROR) {
printf("listen failed with error: %d\n", WSAGetLastError());
closesocket(listen_socket);
WSACleanup();
return 1;
}
cout << "Server initalized successfully. Waiting on client connections. 0/" << MAX_CLIENTS << endl;
memset(recv_buffer, 0, DEFAULT_BUFLEN);
while (true) {
while (clients < MAX_CLIENTS) {
client_socket = SOCKET_ERROR;
while (client_socket == SOCKET_ERROR) {
client_socket = accept(listen_socket, NULL, NULL);
}
client.client_socket = client_socket;
clients++;
cout << "Client connected. Number of connected clients: " << clients << '/' << MAX_CLIENTS << endl;
/*
* Initial connection. Asking for name.
*/
recv(client.client_socket, recv_buffer, DEFAULT_BUFLEN, 0);
cout << "Debug, name recieved. Name is: " << recv_buffer << endl;
/*
* Name put inside structure.
*/
client.client_name = recv_buffer;
ctx = &client;
hThread = (HANDLE)_beginthreadex(NULL, 0, &handle_client, ctx, 0, &threadID);
client.connected_clients.push_back(client.client_socket);
memset(recv_buffer, 0, DEFAULT_BUFLEN);
}
}
return 0;
}

Related

How to measure the delay of sending coordinates over a socket?

I have written code in C++ which takes the x and y coordinates of a robot and sends them across a socket using a little endian. The x and y coordinates are then received on the client end of the socket where they are used to control an actor in a game. All of my code works well but I would like to analyse how efficiently the coordinates are sent and received and to do this i would like to measure the delay in the sending of the coordinates.
I looked into this and saw that getting the time that the coordinate was sent and received and then calculating the difference was the way most people spoke about doing this. However, i am just confused how i would do this in my code as i have measured the time for the program to start up the robot by using int Start = Clock() and int End = Clock() and then getting the difference. But i don't know if this would be the most effective or accurate way of measuring the delay across the socket. So, i was wondering if anybody could suggest a way in which i could do this using the code below. The server sends the coordinates, and the client receives the coordinates.
SERVER code:
#undef UNICODE
#include "pch.h"
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <chrono>
// Need to link with Ws2_32.lib
#pragma comment (lib, "Ws2_32.lib")
// #pragma comment (lib, "Mswsock.lib")
//#define DEFAULT_BUFLEN 8
#define DEFAULT_BUFLEN 5000
#define DEFAULT_PORT "27015"
//two structures for converting the x and y back into doubles/floats
union {
float myFloatx;
unsigned char myCharsx[sizeof(float)];
} testx;
union {
float myFloaty;
unsigned char myCharsy[sizeof(float)];
} testy;
double x;
double y;
int __cdecl main(void)
{
int start = clock();
WSADATA wsaData;
int iResult;
double x;
double y;
SOCKET ListenSocket = INVALID_SOCKET;
SOCKET ClientSocket = INVALID_SOCKET;
struct addrinfo* result = NULL;
struct addrinfo hints;
int iSendResult;
char recvbuf[DEFAULT_BUFLEN];
int recvbuflen = DEFAULT_BUFLEN;
//added (to send back bytes to client)----------------
SOCKET ConnectSocket = INVALID_SOCKET;
char sendvbuf[8];
int sendvbuflen = 8;
//---------------------------------------------
//Creating instances of the classes -------------------------------------------------------------------------------------------------------
Articares::Core::ArticaresComm instance;
Articares::Core::HMANData instance2;
Articares::Core::TargetParams instance3;
//Connecting to HMan -------------------------------------------------------------------------------------------------------
instance.EstablishConnection("192.168.102.1", 3000);
int end = clock();
int time = end - start;
std::cout << "time to connect = " << time << "\n";
//Starting the exercise and setting the targets --------------------------------------------------------------------------
instance.StartExercise(3);
instance.SetTransitionTime(8000, 1, 0);
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed with error: %d\n", iResult);
return 1;
}
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
// Resolve the server address and port
iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);
if (iResult != 0) {
printf("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
return 1;
}
// Create a SOCKET for connecting to server
ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if (ListenSocket == INVALID_SOCKET) {
printf("socket failed with error: %ld\n", WSAGetLastError());
freeaddrinfo(result);
WSACleanup();
return 1;
}
// Setup the TCP listening socket
iResult = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen);
if (iResult == SOCKET_ERROR) {
printf("bind failed with error: %d\n", WSAGetLastError());
freeaddrinfo(result);
closesocket(ListenSocket);
WSACleanup();
return 1;
}
freeaddrinfo(result);
printf("listening\n");
iResult = listen(ListenSocket, SOMAXCONN);
if (iResult == SOCKET_ERROR) {
printf("listen failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
// Accept a client socket
ClientSocket = accept(ListenSocket, NULL, NULL);
if (ClientSocket == INVALID_SOCKET) {
printf("accept failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
//sleep command added to stop the targets moving before the on game instructions have been read by the user
Sleep(80);
//Set target 1 with targetx = 10mm and targety = 10 mm, ‘StiffnessX’ = 100 N/m, ‘StiffnessY’ = 100 N/m, ‘target gain’ = 1,
//IF WISHING TO INCREASE THE RESISTANCE PLEASE INCREASE THE 4TH AND 5TH VALUES IN THE SetTarget() function:
instance.SetTarget("1", "10", "10", "50", "50", "0", "0", "0", "0", "0", "0", "1", "0");
instance.SetTarget("2", "10", "50", "50", "50", "0", "0", "0", "0", "0", "0", "1", "0");
instance.SetTarget("3", "50", "10", "50", "50", "0", "0", "0", "0", "0", "0", "1", "0");
// No longer need server socket
closesocket(ListenSocket);
// Receive until the peer shuts down the connection
do {
while (recv(ClientSocket, recvbuf, recvbuflen, MSG_PEEK) < 8) { ; }
iResult = recv(ClientSocket, recvbuf, recvbuflen, 0);
//std::cout << " hello" << recvbuf << std::endl;
if (iResult > 0) {
printf("Bytes received: %d\n", iResult);
// Echo the buffer back to the sender
iSendResult = send(ClientSocket, recvbuf, iResult, 0);
if (iSendResult == SOCKET_ERROR) {
printf("send failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
printf("Bytes sent: %d\n", iSendResult);
}
else if (iResult == 0)
printf("Connection closing...\n");
else {
printf("recv failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
} while (false);
//Start:; allows the continual sending of coordinates to occur meaning that the program will not shutdown unless it is shutdown from the client end.
Start:;
for (int i = 0; i < 50; i++)
{
std::cout << i << "\n";
Sleep(20);
// Send an initial buffer
double x = instance.hman_data.location_X;
double y = instance.hman_data.location_Y;
//following sends the doubles as char to the receiver
testx.myFloatx = x;
sendvbuf[0] = (int)testx.myCharsx[3];
sendvbuf[1] = (int)testx.myCharsx[2];
sendvbuf[2] = (int)testx.myCharsx[1];
sendvbuf[3] = (int)testx.myCharsx[0];
testy.myFloaty = y;
sendvbuf[4] = (int)testy.myCharsy[3];
sendvbuf[5] = (int)testy.myCharsy[2];
sendvbuf[6] = (int)testy.myCharsy[1];
sendvbuf[7] = (int)testy.myCharsy[0];
//changed the length of the buffer sent as it was causing problems with sending coordinates.
iResult = send(ClientSocket, sendvbuf, 8, 0);
std::cout << "X = " << x << " " << "Y = " << y << "\n";
Sleep(200);
if (iResult == SOCKET_ERROR) {
printf("send failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
}
goto Start;
// shutdown the connection since we are done
iResult = shutdown(ClientSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
// cleanup
closesocket(ClientSocket);
WSACleanup();
CLIENT code:
#include "Control.h"
#include "control.h"
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string>
// Need to link with Ws2_32.lib, Mswsock.lib, and Advapi32.lib
#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "Mswsock.lib")
#pragma comment (lib, "AdvApi32.lib")
//#define DEFAULT_BUFLEN 512
#define DEFAULT_BUFLEN 5000
#define DEFAULT_PORT "27015"
#include "Components/StaticMeshComponent.h"
//Below the "unions" are called labels and these allow for the conversion of the bytes back to a numerical value i.e. coordinate
union {
float myFloatx;
unsigned char myCharsx[sizeof(float)];
} testx;
union {
float myFloaty;
unsigned char myCharsy[sizeof(float)];
} testy;
//Declaring global variables
SOCKET ClientSocket = INVALID_SOCKET;
WSADATA wsaData;
SOCKET ConnectSocket = INVALID_SOCKET;
struct addrinfo* result = NULL,
* ptr = NULL,
hints;
char sendvbuf[8];
char recvbuf[8];
int iResult;
int iSendResult;
int recvbuflen = 8;
int sendvbuflen = 8;
double x;
double y;
// Sets default values
AControl::AControl()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
//Creating an instance of the Root component and allows it to be seen in the editor and game for editing e.g. scale
Root = CreateDefaultSubobject<USceneComponent>(TEXT("Root"));
RootComponent = Root;
//Creating and assigning the static mesh component
Mesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Mesh"));
//want to connect the static mesh with the root component so the pawn component can be edited in the editor
Mesh->AttachTo(Root);
}
// Called when the game starts or when spawned
void AControl::BeginPlay()
{
//////Below has the purpose of starting up the server: -----------------------------------------------
wchar_t command[] = L"C:\\Users\\CCRT\\Documents\\UPDATED\\FINALSERVER\\FINALSERVER\\Debug\\FINALSERVER.exe";
// Start the child process.
STARTUPINFOW si{ sizeof(STARTUPINFOW) };
PROCESS_INFORMATION pi;
if (!CreateProcessW(NULL, // No module name (use command line)
command, // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, // Set handle inheritance to FALSE
0, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi) // Pointer to PROCESS_INFORMATION structure
)
{
std::cout<< "CreateProcess failed\n";
}
else {
std::cout << "Command success\n";
}
//Below makes the client repeatedly search for the server until it connects with it.
int connected = 0;
while (connected == 0)
{
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
//printf("WSAStartup failed with error: %d\n", iResult);
std::cout << "WSAStartup failed with error: %d\n";
//return 1;
goto finish;
}
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
// Resolve the server address and port
iResult = getaddrinfo("127.0.0.1\0", DEFAULT_PORT, &hints, &result);
if (iResult != 0) {
//printf("getaddrinfo failed with error: %d\n", iResult);
std::cout << "getaddrinfo failed with error\n";
WSACleanup();
//return 1;
goto finish;
}
// Attempt to connect to an address until one succeeds
for (ptr = result; ptr != NULL; ptr = ptr->ai_next) {
// Create a SOCKET for connecting to server
ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype,
ptr->ai_protocol);
if (ConnectSocket == INVALID_SOCKET) {
//printf("socket failed with error: %ld\n", WSAGetLastError());
std::cout << "socket failed with error\n";
WSACleanup();
//return 1;
goto finish;
}
// Connect to server.
iResult = connect(ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
if (iResult == SOCKET_ERROR) {
closesocket(ConnectSocket);
ConnectSocket = INVALID_SOCKET;
continue;
}
break;
}
freeaddrinfo(result);
if (ConnectSocket == INVALID_SOCKET) {
//printf("Unable to connect to server!\n");
std::cout << "Unable to connect to server!\n";
WSACleanup();
}
else
{
connected = 1;
}
}
iResult = send(ConnectSocket, sendvbuf, (int)sendvbuflen, 0);
if (iResult == SOCKET_ERROR) {
//printf("send failed with error: %d\n", WSAGetLastError());
std::cout << "send failed with error:\n";
closesocket(ConnectSocket);
WSACleanup();
//return 1;
goto finish;
}
std::cout << "Bytes Sent " << iResult << " " << sendvbuf[1] << std::endl;
finish:;
Super::BeginPlay();
}
// Called every frame
void AControl::Tick(float DeltaTime)
{
// Following recieves the coordinates from the server:
while (recv(ConnectSocket, recvbuf, recvbuflen, MSG_PEEK) < 8) { ; }
iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
if (iResult > 0) {
printf("Bytes received: %d\n", iResult);
//the following turns the chars recieved back into the double format (uses the labels which were declared before)
testx.myCharsx[0] = recvbuf[3];
testx.myCharsx[1] = recvbuf[2];
testx.myCharsx[2] = recvbuf[1];
testx.myCharsx[3] = recvbuf[0];
x = testx.myFloatx;
testy.myCharsy[0] = recvbuf[7];
testy.myCharsy[1] = recvbuf[6];
testy.myCharsy[2] = recvbuf[5];
testy.myCharsy[3] = recvbuf[4];
y = testy.myFloaty;
std::cout << std::endl;
FVector NewLocation = GetActorLocation();
FRotator NewRotation = GetActorRotation();
// NewLocation.X = -y is corrct way round for the HMan to control the ball.
//NewLocation.Y = -x
//IF THE USER IS NEEDING MORE ASSISTANCE THE X AND Y COORDINATES CAN BE SCALED UP BELOW BY MULTIPLYING THEM BY A HIGHER VALUE:--------------------------------------------------------------------------
NewLocation.X = -y *150000;
NewLocation.Y = -x *150000;
NewLocation.Z = 0;
NewRotation.Roll = 0;
NewRotation.Pitch = 0;
NewRotation.Yaw = 0;
SetActorLocationAndRotation(NewLocation, NewRotation, true);
//the true is added to stop the actor moving through walls.
printf("NEW Y: %f\n", NewLocation.Y);
printf("NEW X: %f\n", NewLocation.X);
}
else if (iResult == 0)
//printf("Connection closing...\n");
std::cout << "Connection closing...\n";
else {
//printf("recv failed with error: %d\n", WSAGetLastError());
std::cout << "recv failed with error:\n";
closesocket(ClientSocket);
WSACleanup();
//return 1;
goto finish;
}
finish:;
Super::Tick(DeltaTime);
}
Thanks for any help.

How to receive and parse requests as an HTTP server?

For a class I have to implement an HTTP web server in C++. I currently have the server to the point that it can listen and accept connections, but I can't figure out how to accept data and parse it. When I send a request I get an error saying "Transport endpoint is nt connected." Here's what my code looks like so far:
int main(int argc, char *argv[]) {
// parse CLI args
if (argc != 3) { /** change to 3 once DOCROOT is added */
cout << "invalid arguments" << endl;
exit(1);
}
const char *DOCROOT = argv[1];
const char *PORT = argv[2];
// declare vars....from beej's so some not in use yet
int sockfd, new_fd;
struct addrinfo hints, *servinfo, *p;
struct sockaddr_storage their_addr;
socklen_t sin_size;
struct sigaction sa;
int yes = 1;
char s[INET6_ADDRSTRLEN];
int rv;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
// try getaddrinfo
if ((rv = getaddrinfo(nullptr, PORT, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
return 1;
}
// loop through getaddrinfo response and bind when possible
for (p=servinfo; p!=nullptr; p=p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) {
perror("server: socket");
continue;
}
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
perror("setsockopt");
exit(1);
}
if (::bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
close(sockfd);
perror("server: bind");
continue;
}
break;
}
freeaddrinfo(servinfo);
if (p == nullptr) {
fprintf(stderr, "server: failed to bind\n");
exit(1);
}
/** choose backlog number and declare constant */
if (listen(sockfd, 5) == -1) {
perror("listen");
exit(1);
}
sa.sa_handler = sigchld_handler; // reap all dead processes
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
if (sigaction(SIGCHLD, &sa, nullptr) == -1) {
perror("sigaction");
exit(1);
}
printf("server: waiting for connections on port %s...\n", PORT);
while(true) { /** this will be the main accept loop */
sin_size = sizeof their_addr;
new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
if (new_fd == -1) {
perror("accept");
continue;
}
inet_ntop(their_addr.ss_family,
get_in_addr((struct sockaddr *)&their_addr),
s, sizeof s);
printf("server: got connection from %s\n", s);
// receive
char recvbuf[1024];
int recvbuflen = 1024;
int request = recv(sockfd, recvbuf, recvbuflen, 0);
if (request == -1) perror("error receiving data");
if(send(new_fd, "Data received", 15, 0) == -1)
perror("send");
close(new_fd);
exit(0);
}
return 0;
}

Multi Client TCP server C++ issue

I have made Mutlti-Client sever that can receive and send messages to the sever and the sever can send back the messages to clients but the problem I'm having is client A will not be able to receive the message from client B unless Client A sends a message I want the clients to receive messages anytime I also want to be to type commands on the sever without stopping the flow of sending to clients and receiving message from clients
I have tried moving the std::getline(std::cin, ClientInput); to different place in the code so clients could be able to see message but I have notice in the code the while loop does not continue because of it is there a way to get user input with out stopping the loop so can send and receive messages
This the Client code
int Client::OnCreate()
{
WSADATA wsaData;
SOCKET ConnectSocket = INVALID_SOCKET;
struct addrinfo *result = NULL, *ptr = NULL, hints;
char sendbuf[] = "this is a test";
std::vector<SOCKET> ConnectedUser;
char recvbuf[DEFAULT_BUFLEN];
int iResult;
int recvbuflen = DEFAULT_BUFLEN;
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed with error: %d\n", iResult);
system("pause");
return 1;
}
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
// Resolve the server address and port
iResult = getaddrinfo("localhost", DEFAULT_PORT, &hints, &result);
if (iResult != 0) {
printf("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
system("pause");
return 1;
}
// Attempt to connect to an address until one succeeds
for (ptr = result; ptr != NULL; ptr = ptr->ai_next) {
// Create a SOCKET for connecting to server
ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
if (ConnectSocket == INVALID_SOCKET) {
printf("socket failed with error: %ld\n", WSAGetLastError());
WSACleanup();
system("pause");
return 1;
}
// Connect to server.
iResult = connect(ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
if (iResult == SOCKET_ERROR) {
closesocket(ConnectSocket);
ConnectSocket = INVALID_SOCKET;
continue;
}
break;
}
freeaddrinfo(result);
if (ConnectSocket == INVALID_SOCKET) {
printf("Unable to connect to server!\n");
WSACleanup();
system("pause");
return 1;
}
// Send an initial buffer
std::string ClientInput;
std::cout << "please send a message " << std::endl;
std::getline(std::cin, ClientInput);
do {
if (ClientInput.size() > 0)
{
//send user input to sever
iResult = send(ConnectSocket, ClientInput.c_str(), ClientInput.size(), 0);
if (iResult == SOCKET_ERROR) {
printf("send failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
system("pause");
return 1;
}
printf("Bytes Sent: %d\n", iResult);
if (iResult != SOCKET_ERROR)
{
//receive user input from sever
int iUserResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
if (iUserResult > 0)
{
std::cout << "Client receive this message from sever \t" << std::string(recvbuf, 0, iResult) << std::endl;
printf("Bytes received: %d\n", iUserResult);
}
}
//will disconnect from the sever
if (iResult == SOCKET_ERROR)
{
printf("send failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
system("pause");
}
//will disconnect from the sever if user types in logoff
if (ClientInput == "logoff")
{
closesocket(ConnectSocket);
WSACleanup();
printf("Connection closing goodbye sever\n");
system("pause");
}
//close connection if the no user input
if (iResult == 0) {
printf("Connection closed\n");
iResult = shutdown(ConnectSocket, SD_SEND);
}
}
std::getline(std::cin, ClientInput);
} while (ClientInput.size() > 0);
// cleanup
closesocket(ConnectSocket);
system("pause");
WSACleanup();
return 0;
}```
This is the sever code
std::vector<SOCKET> ConnectedUser;
std::vector<int> UserInt;
unsigned __stdcall ClientSession(void *data)
{
char recvbuf[DEFAULT_BUFLEN];
int recvbufleng = DEFAULT_BUFLEN;
int iResult;
int iSendResult;
SOCKET ClientSocket = (SOCKET)data;
struct addrinfo *result = NULL, hints;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
do
{
iResult = recv(ClientSocket, recvbuf, recvbufleng, 0);
///iResult = recv(ClientSocket, recvbuf, sizeof(Player), 0);
std::cout << iResult << std::endl;
if (iResult > 0) {
for (int i = 0; i < ConnectedUser.size(); i++) {
std::cout << "send message to "<< ConnectedUser[i] << std::endl;
//iSendResult = send(ClientSocket, recvbuf, iResult, 0);
iSendResult = send(ConnectedUser[i], recvbuf, iResult, 0);
//ConnectedUser.clear();
//iSendResult = sendto(ConnectedUser[i], recvbuf, iResult, 0, (sockaddr*)&hints, sizeof(hints));
}
std::cout << "ClientSocket" << ClientSocket << std::endl;
if (iSendResult == SOCKET_ERROR)
{
printf("send failed with error: %d \n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
printf("Received Message %.*s\n", iResult, recvbuf);
}
else if (iResult == 0)
{
printf("connection closing.... \n");
std::cout << "user logged off" << ClientSocket << std::endl;
}
else
{
printf("recv failed with error: %d \n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
} while (iResult > 0);
iResult = shutdown(ClientSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed with error: %d \n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
closesocket(ClientSocket);
}
int Sever::OnCreate()
{
WSADATA wsaData;
int iResult;
SOCKET ClientSocket = INVALID_SOCKET;
//send to
char recvbuf[DEFAULT_BUFLEN];
int recvbufleng = DEFAULT_BUFLEN;
int iSendResult;
struct addrinfo *result = NULL, hints;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
//create the winsocket
if (iResult != 0) {
printf("WSAStartup failed: %d\n, iResult");
return 1;
}
iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);
if (iResult != 0) {
printf("getaddrinfo failed: %d\n", iResult);
WSACleanup();
return 1;
}
SOCKET ListenSocket = INVALID_SOCKET;
ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if (ListenSocket == INVALID_SOCKET) {
printf("error at socket(): %d\n", WSAGetLastError());
freeaddrinfo(result);
WSACleanup();
return 1;
}
iResult = bind(ListenSocket, result->ai_addr, int(result->ai_addrlen));
if (iResult == SOCKET_ERROR) {
printf("bind failed with error: %d \n", WSAGetLastError());
freeaddrinfo(result);
closesocket(ListenSocket);
WSACleanup();
return 1;
}
freeaddrinfo(result);
if (listen(ListenSocket, SOMAXCONN) == SOCKET_ERROR) {
printf("Listen failed with error: %d \n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
// Create the master file descriptor set and zero it
fd_set master;
FD_ZERO(&master);
FD_SET(ListenSocket, &master);
fd_set copy = master;
int socketCount = select(0, &copy, nullptr, nullptr, nullptr);
std::cout << " socketCount "<< socketCount << std::endl;
//// Send an initial buffer
//if (socketCount == 0) {
// std::string SeverInput;
// std::cout << "input Server command" << std::endl;
// std::getline(std::cin, SeverInput);
//
// if (SeverInput == "exit")
// {
// closesocket(ClientSocket);
// WSACleanup();
// printf("Connection closing goodbye sever\n");
// }
//}
for (int i = 0; i < socketCount; i++)
{
SOCKET sock = copy.fd_array[i];
if (sock == ListenSocket)
{
//// Accept a new connection
while ((ClientSocket = accept(ListenSocket, NULL, NULL))) {
if (ClientSocket == INVALID_SOCKET) {
printf("Accept failed with error: %d \n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
/* Messtotal.push_back(ClientSocket + "\n");*/
// Add the new connection to the list of connected clients
FD_SET(ClientSocket, &master);
ConnectedUser.push_back(ClientSocket);
std::cout << "client:" << ClientSocket <<" has arrived on sever" <<std::endl;
// Create a new thread for the accepted client (also pass the accepted client socket).
unsigned threadID;
HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, &ClientSession, (void*)ClientSocket, 0, &threadID);
}
}
}
WSACleanup();
printf("Server shutting down ");
return 0;
```}
Moving the std::getline(std::cin, ClientInput) anywhere within loop in client code will not help you becase getline() is a blocking call. In this case you should use threads in client code.
You need to create a new thread in client code with while loop. In this thread you will incoming messages from another client.
Main thread in client code will handle user input from getline() and sending messages via send function within while loop.
For example in your client code you can create thread like this :
m_hTrhead = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)processMessage, (LPVOID)ConnectSocket, CREATE_SUSPENDED, 0);
if (m_hTrhead == NULL)
{
printf("Failed to create thread for receiving messages , error code : %ld \n", GetLastError());
return false;
}
And thread will will process messages in function processMessage like this :
DWORD WINAPI Socket::processMessage(LPVOID lpParam)
{
SOCKET ConnectSocket= reinterpret_cast <SOCKET>(lpParam);
while (WSAGetLastError() != WSAECONNRESET)
{
int iUserResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
if (iUserResult > 0)
{
std::cout << "Client receive this message from sever \t" << std::string(recvbuf, 0, iResult) << std::endl;
printf("Bytes received: %d\n", iUserResult);
}
}
}
Be aware that non- blocking sockets exists also (So thread will not stop at recv or send function). Function names for non-blocking socket are the same but you must set the socket itself to non-blocking.
u_long mode = 1; // enable non-blocking socket
ioctlsocket(sock, FIONBIO, &mode);
You can read about this more here

WTSEnumerateProcesses with socket and data struct

I'm new with C++ Windows API and I've got few questions about using the WTSEnumerateProcesses() API.
My target: use WTSEnumerateProcesses(), take only the process list, put it in any kind of "list" or struct, convert the widechar to ANSI, and send it to a socket using Winsock.
That's my code below:
Winsock:
int connect(char buffer[])
{
PCSTR ip = "localhost";
WSADATA wsaData;
SOCKET ConnectSocket = INVALID_SOCKET;
struct addrinfo *result = NULL,
*ptr = NULL,
hints;
const char *sendbuf =buffer;
char recvbuf[DEFAULT_BUFLEN];
int iResult;
int recvbuflen = DEFAULT_BUFLEN;
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed with error: %d\n", iResult);
return 1;
}
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
// Resolve the server address and port
iResult = getaddrinfo(ip, DEFAULT_PORT, &hints, &result);
if (iResult != 0) {
printf("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
return 1;
}
// Attempt to connect to an address until one succeeds
for (ptr = result; ptr != NULL; ptr = ptr->ai_next) {
// Create a SOCKET for connecting to server
ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
if (ConnectSocket == INVALID_SOCKET) {
printf("socket failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return 1;
}
// Connect to server.
iResult = connect(ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
if (iResult == SOCKET_ERROR) {
closesocket(ConnectSocket);
ConnectSocket = INVALID_SOCKET;
continue;
}
break;
}
freeaddrinfo(result);
if (ConnectSocket == INVALID_SOCKET) {
printf("Unable to connect to server!\n");
WSACleanup();
return 1;
}
// Send an initial buffer
iResult = send(ConnectSocket, sendbuf, (int)strlen(sendbuf), 0);
if (iResult == SOCKET_ERROR) {
printf("send failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
printf("Bytes Sent: %ld\n", iResult);
// shutdown the connection since no more data will be sent
iResult = shutdown(ConnectSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
// Receive until the peer closes the connection
do {
iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
if (iResult > 0)
printf("Bytes received: %d\n", iResult);
else if (iResult == 0)
printf("Connection closed\n");
else
printf("recv failed with error: %d\n", WSAGetLastError());
}
while (iResult > 0);
// cleanup
closesocket(ConnectSocket);
WSACleanup();
return 0;
}
and the WTSEnumerateProcesses():
void GetProcesslist()
{
vector<LPWSTR> v; // no need to prepend std:: any more
LPWSTR pProcessName;
WTS_PROCESS_INFO* pWPIs = NULL;
DWORD dwProcCount = 0;
if (WTSEnumerateProcesses(WTS_CURRENT_SERVER_HANDLE, NULL, 1, &pWPIs, &dwProcCount))
{
//Go through all processes retrieved
for (DWORD i = 0; i < dwProcCount; i++)
{
pProcessName = pWPIs[i].pProcessName;
v[i] = pProcessName;
//contains(pProcessName);
// process file name only, no path!
//data = pProcessName;
std::wcout << pProcessName << endl;
//pWPIs[i].ProcessId = process ID
//pWPIs[i].SessionId = session ID, if you need to limit it to the logged in user processes
//pWPIs[i].pUserSid = user SID that started the process
}
}
//Free memory
if (pWPIs)
{
WTSFreeMemory(pWPIs);
pWPIs = NULL;
}
}
Can you please help me to understand how I can take the process list only, push it to any struct (like a list?) and send it correctly over the TCP socket, that is waiting to get a const char[] and not wide characters?
You are not using std::vector correctly in your GetProcesslist(). You are trying to access elements you have not allocated any memory for. And worse, you are storing pointers to data that you free before GetProcesslist() exits, leaving the vector containing dangling pointers (were you to access that vector outside of GetProcesslist(), which you are not doing yet).
Try something more like this:
std::vector<std::wstring> GetProcesslist()
{
std::vector<std::wstring> v;
WTS_PROCESS_INFO* pWPIs = NULL;
DWORD dwProcCount = 0;
if (WTSEnumerateProcesses(WTS_CURRENT_SERVER_HANDLE, NULL, 1, &pWPIs, &dwProcCount))
{
//Go through all processes retrieved
for (DWORD i = 0; i < dwProcCount; ++i)
{
LPWSTR pProcessName = pWPIs[i].pProcessName;
v.push_back(pProcessName);
// process file name only, no path!
//data = pProcessName;
std::wcout << pProcessName << endl;
//pWPIs[i].ProcessId = process ID
//pWPIs[i].SessionId = session ID, if you need to limit it to the logged in user processes
//pWPIs[i].pUserSid = user SID that started the process
}
//Free memory
WTSFreeMemory(pWPIs);
}
return v;
}
Then, I would suggest sending the data over the socket like this:
int connect(const char buffer[], size_t buffersize)
{
PCSTR ip = "localhost";
WSADATA wsaData;
SOCKET ConnectSocket = INVALID_SOCKET;
struct addrinfo *result = NULL,
*ptr = NULL,
hints;
const char *sendbuf = buffer;
char recvbuf[DEFAULT_BUFLEN];
int iResult;
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed with error: %d\n", iResult);
return 1;
}
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
// Resolve the server address and port
iResult = getaddrinfo(ip, DEFAULT_PORT, &hints, &result);
if (iResult != 0) {
printf("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
return 1;
}
// Attempt to connect to an address until one succeeds
for (ptr = result; ptr != NULL; ptr = ptr->ai_next) {
// Create a SOCKET for connecting to server
ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
if (ConnectSocket == INVALID_SOCKET) {
printf("socket failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return 1;
}
// Connect to server.
iResult = connect(ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
if (iResult == SOCKET_ERROR) {
closesocket(ConnectSocket);
ConnectSocket = INVALID_SOCKET;
continue;
}
break;
}
freeaddrinfo(result);
if (ConnectSocket == INVALID_SOCKET) {
printf("Unable to connect to server!\n");
WSACleanup();
return 1;
}
// Send an initial buffer
while (buffersize > 0) {
iResult = send(ConnectSocket, sendbuf, (int)buffersize, 0);
if (iResult == SOCKET_ERROR) {
printf("send failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
printf("Bytes Sent: %ld\n", iResult);
sendbuf += iResult;
buffersize -= iResult;
}
// shutdown the connection since no more data will be sent
iResult = shutdown(ConnectSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
// Receive until the peer closes the connection
do {
iResult = recv(ConnectSocket, recvbuf, sizeof(recvbuf), 0);
if (iResult > 0)
printf("Bytes received: %d\n", iResult);
else if (iResult == 0)
printf("Connection closed\n");
else
printf("recv failed with error: %d\n", WSAGetLastError());
}
while (iResult > 0);
// cleanup
closesocket(ConnectSocket);
WSACleanup();
return 0;
}
std::vector<std::wstring> procs = GetProcesslist();
std::vector<char> buffer;
size_t size = sizeof(uint32_t);
for(const std::wstring &name : procs) {
size += (sizeof(uint32_t) + WideCharToMultiByte(CP_UTF8, 0, name.c_str(), name.size(), NULL, 0, NULL, NULL));
}
buffer.resize(size);
char *ptr = buffer.data();
*reinterpret_cast<uint32_t*>(ptr) = htonl(procs.size());
ptr += sizeof(uint32_t);
for(const std::wstring &name : procs) {
int len = WideCharToMultiByte(CP_UTF8, 0, name.c_str(), name.size(), NULL, 0, NULL, NULL));
*reinterpret_cast<uint32_t*>(ptr) = htonl(len);
ptr += sizeof(uint32_t);
if (len > 0) {
ptr += WideCharToMultiByte(CP_UTF8, 0, name.c_str(), name.size(), ptr, len, NULL, NULL));
}
}
connect(buffer.data(), buffer.size());
Or, if you absolutely cannot change the signature of connect() and must pass it a null-terminated C string, then try this:
int connect(const char buffer[])
{
PCSTR ip = "localhost";
WSADATA wsaData;
SOCKET ConnectSocket = INVALID_SOCKET;
struct addrinfo *result = NULL,
*ptr = NULL,
hints;
const char *sendbuf = buffer;
sendbuflen = strlen(buffer);
char recvbuf[DEFAULT_BUFLEN];
int iResult;
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed with error: %d\n", iResult);
return 1;
}
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
// Resolve the server address and port
iResult = getaddrinfo(ip, DEFAULT_PORT, &hints, &result);
if (iResult != 0) {
printf("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
return 1;
}
// Attempt to connect to an address until one succeeds
for (ptr = result; ptr != NULL; ptr = ptr->ai_next) {
// Create a SOCKET for connecting to server
ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
if (ConnectSocket == INVALID_SOCKET) {
printf("socket failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return 1;
}
// Connect to server.
iResult = connect(ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
if (iResult == SOCKET_ERROR) {
closesocket(ConnectSocket);
ConnectSocket = INVALID_SOCKET;
continue;
}
break;
}
freeaddrinfo(result);
if (ConnectSocket == INVALID_SOCKET) {
printf("Unable to connect to server!\n");
WSACleanup();
return 1;
}
// Send an initial buffer
while (sendbuflen > 0) {
iResult = send(ConnectSocket, sendbuf, sendbuflen, 0);
if (iResult == SOCKET_ERROR) {
printf("send failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
printf("Bytes Sent: %ld\n", iResult);
sendbuf += iResult;
sendbuflen -= iResult;
}
// shutdown the connection since no more data will be sent
iResult = shutdown(ConnectSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
// Receive until the peer closes the connection
do {
iResult = recv(ConnectSocket, recvbuf, sizeof(recvbuf), 0);
if (iResult > 0)
printf("Bytes received: %d\n", iResult);
else if (iResult == 0)
printf("Connection closed\n");
else
printf("recv failed with error: %d\n", WSAGetLastError());
}
while (iResult > 0);
// cleanup
closesocket(ConnectSocket);
WSACleanup();
return 0;
}
std::vector<std::wstring> procs = GetProcesslist();
std::ostringstream oss;
oss << procs.size() << "\x1";
for(const std::wstring &name : procs) {
int len = WideCharToMultiByte(CP_UTF8, 0, name.c_str(), name.size(), NULL, 0, NULL, NULL);
if (len > 0) {
std::string s;
s.resize(len);
WideCharToMultiByte(CP_UTF8, 0, name.c_str(), name.size(), &s[0], len, NULL, NULL);
oss << s;
}
oss << "\x1";
}
connect(oss.str().c_str());

C++ Winsock App Access Violation

I am using the source code from the MSDN for the C++ Winsock Server & Client, on the server side I am putting most of the code in functions and am having a access violation error. My complete source is below.
Any help would be great, thanks in advance!
This is my j420s,cpp file.
#include "j420s.h"
//Source From : MSDN Winsock Server Code.
//Original Source : https ://msdn.microsoft.com/en- us/library/windows/desktop/ms737593(v=vs.85).aspx
int __cdecl main(void) {
WSADATA wsaData;
int iResult = NULL;
SOCKET ListenSocket = INVALID_SOCKET;
SOCKET ClientSocket = INVALID_SOCKET;
struct addrinfo *MySocketResult = NULL;
struct addrinfo MySocket;
int iSendResult;
char recvbuf[DEFAULT_BUFLEN];
int recvbuflen = DEFAULT_BUFLEN;
// Initialize Winsock
iResult = SocketInit(iResult, &wsaData);
if (iResult == 1){
return 1;
}
ZeroMemory(&MySocket, sizeof(MySocket));
MySocket.ai_family = AF_INET;
MySocket.ai_socktype = SOCK_STREAM;
MySocket.ai_protocol = IPPROTO_TCP;
MySocket.ai_flags = AI_PASSIVE;
// Resolve the server address and port
iResult = SocketAddrInfo(iResult, &MySocket, MySocketResult);
// Create a SOCKET for connecting to server
ListenSocket = SocketCreate(ListenSocket, MySocketResult);
if (ListenSocket == 1){
return 1;
}
// Setup the TCP listening socket
iResult = SocketBind(iResult, ListenSocket, MySocketResult);
if (iResult == 1) {
return 1;
}
iResult = SocketListen(iResult, ListenSocket, MySocketResult);
if (iResult == 1) {
return 1;
}
// Accept a client socket
ClientSocket = accept(ListenSocket, NULL, NULL);
if (ClientSocket == INVALID_SOCKET) {
printf("accept failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
// No longer need server socket
closesocket(ListenSocket);
// Receive FOREVER!
while (1 == 1){
do {
iResult = recv(ClientSocket, recvbuf, recvbuflen, 0);
if (iResult > 0) {
printf("Bytes received: %d\n", iResult);
// Echo the buffer back to the sender
iSendResult = send(ClientSocket, recvbuf, iResult, 0);
if (iSendResult == SOCKET_ERROR) {
printf("send failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
printf("Bytes sent: %d\n", iSendResult);
}
} while (iResult > 0);
}
// shutdown the connection since we're done
iResult = shutdown(ClientSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
// cleanup
closesocket(ClientSocket);
WSACleanup();
system("pause");
return 0;
}
int SocketAddrInfo(int iResult, addrinfo* MySocket, addrinfo* MySocketResult){
iResult = getaddrinfo(NULL, DEFAULT_PORT, MySocket, &MySocketResult);
if (iResult != 0) {
printf("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
return 1;
}
return iResult;
}
// Socket initialization
int SocketInit(int iResult, WSADATA *wsaData){
iResult = WSAStartup(MAKEWORD(2, 2), wsaData);
if (iResult != 0) {
printf("WSAStartup failed with error: %d\n", iResult);
std::cout << "Server closing in 5 ";
for (int i = 4; i > 0; i--){
Sleep(1 * 1000);
cout << i << " ";
}
cout << "Server closing now!" << endl;
return 1;
}
return iResult;
}
// Socket create function to create a socket for connecting to our server.
SOCKET SocketCreate(SOCKET ListenSocket, addrinfo* MySocketResult){
ListenSocket = socket( MySocketResult->ai_family, MySocketResult- >ai_socktype, MySocketResult->ai_protocol );
if ( ListenSocket == INVALID_SOCKET ) {
printf("Socket failed with error: %ld\n", WSAGetLastError());
freeaddrinfo(MySocketResult);
WSACleanup();
std::cout << "Server closing in 5 ";
for (int i = 4; i > 0; i--){
Sleep(1 * 1000);
cout << i << " ";
}
cout << "Server closing now!" << endl;
return 1;
}
return ListenSocket;
}
// Socket bind function for binding our socket to an address for incoming connections.
int SocketBind(int iResult, SOCKET ListenSocket, addrinfo* MySocketResult) {
iResult = bind(ListenSocket, MySocketResult->ai_addr, (int)MySocketResult->ai_addrlen);
if (iResult == SOCKET_ERROR) {
printf("Bind failed with error: %d\n", WSAGetLastError());
freeaddrinfo(MySocketResult);
closesocket(ListenSocket);
WSACleanup();
std::cout << "Server closing in 5 ";
for (int i = 4; i > 0; i--){
Sleep(1 * 1000);
cout << i << " ";
}
cout << "Server closing now!" << endl;
return 1;
}
return iResult;
}
// Socket listen function to listen for incoming connections.
int SocketListen(int iResult, SOCKET ListenSocket, addrinfo* MySocketResult) {
freeaddrinfo(MySocketResult);
iResult = listen(ListenSocket, SOMAXCONN);
if (iResult == SOCKET_ERROR) {
printf("Listen failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
std::cout << "Server closing in 5 ";
for (int i = 4; i > 0; i--){
Sleep(1 * 1000);
cout << i << " ";
}
cout << "Server closing now!" << endl;
return 1;
}
return iResult;
}
// Socket accept connection function.
SOCKET SocketAcceptConnection(SOCKET ClientSocket, SOCKET ListenSocket) {
ClientSocket = accept(ListenSocket, NULL, NULL);
if (ClientSocket == INVALID_SOCKET) {
printf("accept failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
std::cout << "Server closing in 5 ";
for (int i = 4; i > 0; i--){
Sleep(1 * 1000);
cout << i << " ";
}
cout << "Server closing now!" << endl;
return 1;
}
closesocket(ListenSocket);
return 0;
}
Here is my j420s.h file.
#undef UNICODE
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
using std::cout;
using std::endl;
// Need to link with Ws2_32.lib
#pragma comment (lib, "Ws2_32.lib")
// #pragma comment (lib, "Mswsock.lib")
#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT "10187"
int SocketInit(int, WSADATA*);
int SocketAddrInfo(int, addrinfo*, addrinfo*);
SOCKET SocketCreate(SOCKET, addrinfo* );
int SocketBind(int, SOCKET, addrinfo* );
int SocketListen(int, SOCKET, addrinfo* );
SOCKET SocketAcceptConnection(SOCKET, SOCKET );
The access violation is somewhere in this function:
int SocketAddrInfo(int iResult, addrinfo* MySocket, addrinfo* MySocketResult){
iResult = getaddrinfo(NULL, DEFAULT_PORT, MySocket, &MySocketResult);
if (iResult != 0) {
printf("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
return 1;
}
return iResult;
}
I call the function like so:
iResult = SocketAddrInfo(iResult, &MySocket, MySocketResult);
I believe it's something to do with my pointers...
Again, any help would be great! Thanks again!
The result from getaddrinfo() will be thrown away on returning from the function SocketAddrInfo(), and MySocketResult in function main() remains NULL.
After that, this NULL is passed to SocketCreate(), and it is dereferenced via MySocketResult. It should cause crush.
You should pass a pointer to MySocketResult to SocketAddrInfo() and have getaddrinfo() modify it.
int SocketAddrInfo(int iResult, addrinfo* MySocket, addrinfo** MySocketResult){
iResult = getaddrinfo(NULL, DEFAULT_PORT, MySocket, MySocketResult);
if (iResult != 0) {
printf("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
return 1;
}
return iResult;
}
How to call:
iResult = SocketAddrInfo(iResult, &MySocket, &MySocketResult);