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.
Related
My code between the client and server works as expected except for the connection closing prematurely after only one message has been sent or received. I want both the client and the server to stay open to send multiple messages without having to reinitialize the connection every time. My code is below:
Server
#undef UNICODE
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
// Need to link with Ws2_32.lib
#pragma comment (lib, "Ws2_32.lib")
#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT "27016"
int __cdecl main(void)
{
WSADATA wsaData;
int iResult;
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;
// 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(0, 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);
std::cout << "Server Starting..." << std::endl;
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);
iResult = listen(ListenSocket, SOMAXCONN);
std::cout << "Waiting for clients..." << std::endl;
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;
}
std::cout << "In the server loop ready to receive a command..." << std::endl;
// No longer need server socket
//closesocket(ListenSocket);
// Receive until the peer shuts down the connection
do {
iResult = recv(ClientSocket, recvbuf, recvbuflen, 0);
if (iResult > 0) {
printf("Bytes received: %d\n", iResult);
std::cout << recvbuf << std::endl;
// Echo the buffer back to the sender
iSendResult = send(ClientSocket, recvbuf, iResult, 0);
if (strcmp(recvbuf, "move") == 0) {
std::cout << "Command received: " << recvbuf << std::endl;
}
else if (strcmp(recvbuf, "stats") == 0) {
std::cout << "Command received: " << recvbuf << std::endl;
}
else if (strcmp(recvbuf, "shoot") == 0) {
std::cout << "Command received: " << recvbuf << std::endl;
}
if (iSendResult == SOCKET_ERROR) {
printf("send failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
}
else if (iResult == 0)
printf("Connection closing...\n");
else {
printf("recv failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
} 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;
}
Client
#define _CRT_SECURE_NO_WARNINGS
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sstream>
#include <iostream>
using std::string;
using std::cin;
// 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_PORT "27016"
int __cdecl main(int argc, char **argv)
{
WSADATA wsaData;
SOCKET ConnectSocket = INVALID_SOCKET;
struct addrinfo *result = NULL,
*ptr = NULL,
hints;
// char *sendbuf = "this is a test"; // disallowed with /permissive- flag
//char *sendbuf = new char[strlen("this is a test")];
char recvbuf[DEFAULT_BUFLEN];
int iResult;
int recvbuflen = DEFAULT_BUFLEN;
// Validate the parameters
if (argc != 2) {
printf("usage: %s server-name\n", argv[0]);
return 1;
}
// 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(argv[1], 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;
}
char *sendbuf = new char[DEFAULT_BUFLEN]();
std::cout << "In the client ready to send a command..." << std::endl;
cin.getline(sendbuf, DEFAULT_BUFLEN);
int size;
for (size = 0; sendbuf[size] != '\0'; size++);
std::cout << sendbuf << std::endl;
// Send an initial buffer
iResult = send(ConnectSocket, sendbuf, size, 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;
}
std::cout << "Command sent: " << sendbuf << std::endl;
// 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());
std::cout << iResult << std::endl;
} while (iResult > 0);
// cleanup
closesocket(ConnectSocket);
WSACleanup();
return 0;
}
I am creating a multi threaded server which will allow for multiple clients to join. But I have recently added this code to my client:
if (CTRL_CLOSE_EVENT == true)
{
send(ConnectSocket, (char*)quit, 1, 0);
iResult = shutdown(ConnectSocket, SD_BOTH);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
This should send a quit message whenever the console is closed, but whenever I close the console it throws a runtime library error and makes me abort. It comes up with recv() function failed and send() function failed, which means the socket hasn't shut down correctly.
Here is my server code:
#undef UNICODE
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
#include <mutex>
#include <iostream>
#include <string>
#include "game.h"
#include <fstream>
// 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 "27015"
#define DEFAULT_IP "127.0.0.1 "
std::mutex MyMutex;
int ClientCount;
using namespace std;
std::ofstream outfile ("serverconfig.txt", std::ofstream::out | std::ofstream::app);
int callThread(SOCKET ClientSocket,int nCount)
{
MyMutex.lock();
char recvbuf[DEFAULT_BUFLEN];
int recvbuflen = DEFAULT_BUFLEN;
int iResult, iSendResult;
// Receive until the peer shuts down the connection
printf("thread count: %d\n", nCount);
do {
iResult = recv(ClientSocket, recvbuf, recvbuflen, 0);
if (iResult == 1)
{
cout << "Client " << nCount << " has left" << endl;
closesocket(ClientSocket);
nCount--;
}
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: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
printf("Bytes sent: %d\n", iSendResult);
}
else if (iResult == 0)
{
nCount--;
printf("Connection closing...\n");
}
else {
printf("recv failed: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
MyMutex.unlock();
}
while (iResult > 0);
}
int __cdecl main(void)
{
WSADATA wsaData;
int iResult;
SOCKET ListenSocket = INVALID_SOCKET;
SOCKET ClientSocket = INVALID_SOCKET;
struct addrinfo *result = NULL;
struct addrinfo hints;
int iSendResult;
ClientCount = 0;
char recvbuf[DEFAULT_BUFLEN];
int recvbuflen = DEFAULT_BUFLEN;
std::thread myThreads[100];
game game1;
string type;
string map;
int level;
int max;
int min;
//output server details to file
ofstream outfile;
outfile.open("serverconfig.txt");
outfile << DEFAULT_IP;
outfile << DEFAULT_PORT;
outfile.close();
//get start up data
/*cout << "please choose a type: 1: Deathmatch 2: Capture the flag 3: Blood Diamond" << endl;
cin >> type;
cout << "Please choose a map:" << endl;
cin >> map;
cout << "please choose a difficulty level between 1 - 3: " << endl;
cin >> level;
cout << "Please choose the max number of clients: " << endl;
cin >> max;
cout << "Please choose the min number of clients" << endl;
cin >> min; */
// 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);
if (listen(ListenSocket, SOMAXCONN) == SOCKET_ERROR) {
printf("Listen failed with error: %ld\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
for (;;)
{
//creating a temp socket for accepting a connction
SOCKET ClientSocket;
// Accept a client socket
ClientSocket = accept(ListenSocket, NULL, NULL);
if (ClientSocket == INVALID_SOCKET) {
printf("accept failed: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
else
{
myThreads[ClientCount] = std::thread(callThread, ClientSocket, ClientCount);
ClientCount++;
printf("normal count: %d\n", ClientCount);
if (ClientCount == 1)
{
cout << "Waiting for another Client to connect" << endl;
}
/*if (ClientCount >= 2)
{
cout << "Game" << type << "in progress" << endl;
}*/
}
}
// 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;
}
And this is my client code:
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
#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_PORT "27015"
using namespace std;
int __cdecl main(int argc, char **argv)
{
WSADATA wsaData;
SOCKET ConnectSocket = INVALID_SOCKET;
struct addrinfo *result = NULL,
*ptr = NULL,
hints;
char *sendbuf = "this is a test";
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("127.0.0.1", 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);
int quit = 1;
// Send and 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());
if (CTRL_CLOSE_EVENT == true)
{
send(ConnectSocket, (char*)quit, 1, 0);
iResult = shutdown(ConnectSocket, SD_BOTH);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
}
}
while (iResult > 0);
// 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;
}
// cleanup
closesocket(ConnectSocket);
WSACleanup();
system("PAUSE");
return 0;
}
I am making a Winsock application, and something fails in the server when it tries to make the shutdown funtion. The project builds and runs, but when the first connection of the client arrives it takes it and fails showing in the comand line:
"shutdown failed with error: 10038".
I have been reading about the error and it is said that it is usually because the funcion shutdown is applied to something that is not a SOCKET, or like that. But when debugging I saw that apparently it is a Socket, so I don't know what to do.
#undef UNICODE
#define WIN32_LEAN_AND_MEAN
#include "stdafx.h"
// 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 "27015"
//Function declaration
const std::string currentDateTime();
int __cdecl NewClient(SOCKET ListenSocket, SOCKET ClientSocket, char *recvbuf, int recvbuflen, int iSendResult, int iResult);
std::string CommandGet(char *recvbuf);
void Login(char *recvbuf);
void print_data(char *recvbuf);
string GetUsername(char *recvbuf);
string GetThirdToken(char *recvbuf);
//Map & Struct creation
struct message{
static unsigned int last_id;
unsigned int id;
std::string baa;
std::string timestamp;
message(){};
message(const std::string& recvbuf_baa,const std::string& a_timestamp) :
baa(recvbuf_baa), timestamp(a_timestamp), id(++last_id)
{
}
};
map<std::string,std::vector<message *> > data;
map<std::string,std::vector<string> > followers;
//Global variables
unsigned int message::last_id = 0;
map<std::string,bool> loggedin;
int __cdecl main(void)
{
WSADATA wsaData;
int iResult;
SOCKET ListenSocket = INVALID_SOCKET;
SOCKET ClientSocket = INVALID_SOCKET;
struct addrinfo *result = NULL;
struct addrinfo hints;
int iSendResult=0;
char recvbuf[DEFAULT_BUFLEN];
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_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
while(true){
// 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);
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;
}
// No longer need server socket
closesocket(ListenSocket);
return NewClient(ListenSocket, ClientSocket, recvbuf, recvbuflen, iSendResult, iResult);
}
}
int __cdecl NewClient(SOCKET ListenSocket, SOCKET ClientSocket, char *recvbuf, int recvbuflen, int iSendResult, int iResult){
// Receive until the peer shuts down the connection
do {
iResult = recv(ClientSocket, recvbuf, recvbuflen, 0);
if (iResult > 0) {
printf("Bytes received: %d\n", iResult);
std::string cmd=CommandGet(recvbuf);
if (cmd=="log"){
std::string usrn=GetUsername(recvbuf);
std::string recvbuf_str="";
for(auto it=loggedin.begin();it!=loggedin.end();it++){
if ((*it).first==usrn){
recvbuf_str="loggedin";
if ((*it).second){
recvbuf_str="cantlogin";
break;
}
else{
loggedin[usrn]=1;
break;
}
break;
}
}
if (recvbuf_str==""){
recvbuf_str="newlogin";
Login(recvbuf);
}
iSendResult = send( ClientSocket, recvbuf_str.c_str(), iResult, 0 );
if (iSendResult == SOCKET_ERROR) {
printf("send failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
}
}
else if (iResult == 0){
printf("Connection closing...\n");
closesocket(ClientSocket);}
else {
printf("recv failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
} 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();
return 0;
}
const std::string currentDateTime() {
time_t now = time(0);
struct tm tstruct;
char buf[80];
localtime_s(&tstruct, &now);
strftime(buf, sizeof(buf), "%Y-%m-%d %X", &tstruct);
return buf;
}
void Login(char *recvbuf){
std::string usrn= GetUsername(recvbuf);
std::vector<message *> messages;
data[usrn]=messages;
std::vector<string> follow;
followers[usrn]=follow;
loggedin[usrn]=1;
}
void print_data(char *recvbuf){
std::string usrn= GetUsername(recvbuf);
for(auto mapIt = data.cbegin(); mapIt != data.cend(); ++mapIt)
{
std::cout << "printing data for " << mapIt->first << ":" << std::endl;
for(auto vectIter = mapIt->second.cbegin(); vectIter != mapIt->second.cend(); ++vectIter)
{
std::cout << (*vectIter)->baa << ", " << (*vectIter)->timestamp << ", "
<< (*vectIter)->id << std::endl;
}
}
}
void print_followers(char *recvbuf){
std::string usrn= GetUsername(recvbuf);
for(auto mapIt = followers.cbegin(); mapIt != followers.cend(); ++mapIt)
{
std::cout << "printing followers for " << mapIt->first << ":" << std::endl;
for(auto vectIter = mapIt->second.cbegin(); vectIter != mapIt->second.cend(); ++vectIter)
{
std::cout << (*vectIter) << endl;
}
}
}
std::string CommandGet(char *recvbuf){
int start0=0;
std::string recvbuf_cmd;
std::string recvstr(recvbuf);
start0=recvstr.find(';');
recvbuf_cmd=recvstr.substr(0,start0);
return recvbuf_cmd;
}
string GetUsername(char *recvbuf){
int start0=0, start1=0;
std::string recvbuf_usrn;
std::string recvstr(recvbuf);
start0=recvstr.find(';');
start1=recvstr.find(';',start0+1);
recvbuf_usrn=recvstr.substr(start0+1,start1-start0-1);
return recvbuf_usrn;
}
string GetThirdToken(char *recvbuf){
int start0=0, start1=0, start2=0;
std::string recvbuf_thirdtoken;
std::string recvstr(recvbuf);
start0=recvstr.find(';');
start1=recvstr.find(';',start0+1);
start2=recvstr.find(';',start1+1);
recvbuf_thirdtoken=recvstr.substr(start1+1,start2-start1-1);
return recvbuf_thirdtoken;
}
I upload the whole project in case you want to check it deeper( https://mega.nz/#!dtcx1DCL!dKWV2ryDDfiXv5H3Mi2p4PrBpie2CGrGJOTAwvQAV8M), but the problem is located in the server(which i simplified the code), the client is just so you can start the conection entering the username(but dont care about it).
Thank you in advance, any help will be appreciated.
Lets consider the following lines, take from your shown source:
iResult = recv(ClientSocket, recvbuf, recvbuflen, 0);
...
else if (iResult == 0){
printf("Connection closing...\n");
closesocket(ClientSocket);}
...
iResult = shutdown(ClientSocket, SD_SEND);
When recv returns zero that means the connection has been closed (nicely) by the other end. When that happens you call closesocket to close the socket. But then you proceed to unconditionally call shutdown on the closed socket, leading to the error you got.
Simple solution? Just close the socket using closesocket once, no need for shutdown here that I can see (there seldom are).
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);
We are building a program that has a server streaming video from a client. We are using C++ in visual studio. Running in debug mode takes away all weird symptoms.
OBS: running in release but turning of optimizations with /0d still gives the symptoms.
Symptoms: While calling imshow("blabla", image); in the server we get the following error: "Unhandled exception at 0x54F26AF8 (opencv_highgui248d.dll) in newCVS2.exe: 0xC0000005: Access violation reading location 0x69577265."
However if we do a imwrite("example.jpg", otherimage); before we do not get this error. image and otherimage are different images. We have tried stepping through the code, no strange jumps are done that I know of.
In the code below search for imwrite("test.jpg",tmp3) with the code below we will get the error, if imwrite is uncommented we will not. I included all the code for reference.
OBS: imwrite solves the problem it is not the cause of it!
thanks in advance, any comments appreciated.
Example of code:
// newCVS2.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#undef UNICODE
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <process.h>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#pragma comment (lib, "Ws2_32.lib")
using namespace std;
using namespace cv;
void streamServer(void* arg);
void quit(string msg, int retval);
int connect();
//HANDLE hMutex1;
Mat frame;
Mat img;
SOCKET ListenSocket;
SOCKET ClientSocket;
WSADATA wsaData;
int iResult;
#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT "27015"
int iSendResult;
char recvbuf[DEFAULT_BUFLEN];
int recvbuflen = DEFAULT_BUFLEN;
int is_data_ready = 0;
HANDLE hMutex1 = CreateMutex( NULL, FALSE, NULL );
HANDLE syncMutex = CreateMutex( NULL, FALSE, NULL );
void streamServer(void* arg){
int imgSize = img.total()*img.elemSize();
char* sockData = new char[imgSize];
int bytes=0;
int errorMsg = connect();
if(errorMsg != 0){
cout << "error on: " << errorMsg;
}
SYSTEMTIME before;
SYSTEMTIME after;
// Receive until the peer shuts down the connection
memset(sockData, 0x0, sizeof(sockData));
do {
GetSystemTime(&before);
for(int i = 0; i < imgSize; i += iResult){
iResult = recv(ClientSocket, sockData + i, imgSize - i, 0);
if(iResult == -1){
printf("resv failed");
}
}
GetSystemTime(&after);
cout << (((after.wSecond * 1000) + after.wMilliseconds) - ((before.wSecond * 1000 ) + before.wMilliseconds)) << " time for recv \n";
//int ptr = 0;
GetSystemTime(&before);
WaitForSingleObject( hMutex1, INFINITE );
for(int i = 0; i < img.rows; i++){
//row = sockData.part(
for(int j = 0; j < img.cols; j++){
(img.row(i)).col(j) = (uchar)sockData[((img.cols)*i)+j];
//img.at<cv::Vec3b>(i,j) = cv::Vec3b((uchar)sockData[ptr+ 0],(uchar)sockData[ptr+1],(uchar)sockData[ptr+2]);
//ptr = ptr + 3;
}
}
cout << img.rows << " number of rows ";
GetSystemTime(&after);
is_data_ready = 1;
memset(sockData, 0x0, sizeof(sockData));
ReleaseMutex( hMutex1 );
cout << (((after.wSecond * 1000) + after.wMilliseconds) - ((before.wSecond * 1000 ) + before.wMilliseconds)) << " time for annoying shit \n";
if (iResult > 0) {
printf("Bytes received: %d\n", iResult);
}
//Close the connection
else if (iResult == 0)
printf("Connection closing...\n");
//Fail during connection
else {
printf("recv failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
}
} 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();
}
// cleanup
closesocket(ClientSocket);
WSACleanup();
}
int main()
{
int width, height;
width = 640;
height = 480;
img = Mat::zeros( height,width, CV_8UC1);
is_data_ready = 0; // not needed
_beginthread( streamServer, 0, NULL );
//needed to make sure that server does not close
while(true){
WaitForSingleObject( hMutex1, INFINITE );
if(is_data_ready){
cout << img.rows << " number rows before show \n";
cout << img.empty() << " empty? \n";
WaitForSingleObject( syncMutex, INFINITE );
Mat tmp0, tmp1, tmp2, tmp3, tmp4;
tmp4 = img;
bilateralFilter(img, tmp0, -1, 50, 5);
Canny(tmp0, tmp1, 35, 200, 3);
/*imwrite("test.jpg",tmp3);
waitKey(1);*/
ReleaseMutex( syncMutex );
WaitForSingleObject( syncMutex, INFINITE );
imshow("ServerWindow", tmp1);
ReleaseMutex( syncMutex );
waitKey(1);
cout << img.cols << " number cols after show \n";
is_data_ready = 0;
}
ReleaseMutex( hMutex1 );
waitKey(1);
}
//connect();
return 0;
}
void quit(string msg, int retval){
}
int connect(){
/*WSADATA wsaData;
int iResult;
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;*/
struct addrinfo *result = NULL;
struct addrinfo hints;
ListenSocket = INVALID_SOCKET;
ClientSocket = INVALID_SOCKET;
// 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);
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;
}
// No longer need server socket
closesocket(ListenSocket);
return 0;
}
Edit:
If adding the test if tmp1 is empty as suggested I get another exception:
bilateralFilter(img, tmp0, -1, 50, 5);
Canny(tmp0, tmp1, 35, 200, 3);
//ytp = frame;
//testImage = frame;
imwrite("test.jpg",tmp3);
waitKey(1);
waitKey(500);
ReleaseMutex( syncMutex );
WaitForSingleObject( syncMutex, INFINITE );
if (tmp1.empty()) {
std::cout << "tmp1 is empty" << std::endl;
break;
}
imshow("ServerWindow", tmp1);
the program now crashes on imwrite and throws the exception:
Unhandled exception at 0x67BDFF1F (msvcr110d.dll) in newCVS2.exe: 0xC0000005: Access violation reading location 0x67706A2E.
it is making me think that there is some problem accessing the mats
Check if tmp1 is not empty, for example
if (tmp1.empty) {
std::cout << "tmp1 is empty" << std::endl;
break;
}
I noticed that OpenCV's imshow function is not thread-safe (at least on Windows machine). For example, if I call imshow from two different threads my program would crush. The program would also crush if I called namedWindow() command in one thread and then imshow() command in another thread. So make sure you don't do that. As a side note, it is better to create an output window using namedWindow("ServerWindow"), before calling imshow. Create this window only once (outside of the for loop) and in the same thread where you call imshow. This will improve the performance and may fix the issue.
It is because tmp3 is only initialized, it does not have any data. Trying to write tmp0 or tmp1 will work in this code.