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.
Related
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.
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);
I'm trying to make a chess game, through sockets.
There is a server that is responsible for sending the board to the players, to get the input and response and so on..
I've tried to create a client-server (actually 2clients and server) but it doesn't work.
The clients connect to the server properly, but the data that is delieved doesn't correct.
For example, I send "E2-C3" from the client ; the recv result (on the server side) is always 0, or it prints garbage.
Client :
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string>
#include <sys/types.h>
// 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")
using namespace std;
#define SERVER_IP "1.1.1.1"
#define SERVER_PORT 8888
#define BUFFER_SIZE 1024
// server side
#define INVALID_MOVE 00
#define PLEASE_ENTER_A_MOVE 15
#define PRINT_BOARD 20
#define END_GAME 30
// client side
#define MOVE 10
int __cdecl main()
{
WSADATA info;
int errorDATA; // configuriation
int socketCreate; // create the socket - empty
SOCKADDR_IN ClientService; // configuriation (stage 3) - data of the server.
int connectResult;
char sendBuf[1024], recvbuf[1024];
int iResult;
/*Configuration*/
errorDATA = WSAStartup(MAKEWORD(2, 2), &info);
if (errorDATA == INVALID_SOCKET)
{
printf("WSAStartup failed with error : %d\n", errorDATA);
return -1;
}
/*Create empty socket*/
socketCreate = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // creating the socket "Clean - empty"
if (socketCreate == INVALID_SOCKET)
{
printf("Error number %d in creating socket!\n", WSAGetLastError());
return -1;
}
printf("Creating socket SUCCEEDED!\n");
/*Confugirate the created socket*/
ClientService.sin_family = AF_INET;
ClientService.sin_addr.s_addr = inet_addr(SERVER_IP); // server's ip
ClientService.sin_port = htons(SERVER_PORT);
/*Asking for connection*/
connectResult = connect(socketCreate, (struct sockaddr*) &ClientService, sizeof(ClientService));
while (1)
{
cout << "Please enter a move : " << endl;
cin >> sendBuf;
iResult = send(socketCreate, sendBuf, (int)strlen(sendBuf), 0);
if (iResult == SOCKET_ERROR) {
printf("send failed with error: %d\n", WSAGetLastError());
closesocket(socketCreate);
WSACleanup();
return 1;
}
// MOVE
iResult = recv(socketCreate, recvbuf, strlen(recvbuf), 0);
if (iResult > 0)
{
if (recvbuf[0] == '0' && recvbuf[1] == '0')
{
cout << "You've entered an illegal move. Please try again." << endl;
continue;
}
else if (recvbuf[0] == '2' && recvbuf[1] == '0')
{
// print the board.
bool keepGoing = 0;
do
{
iResult = recv(socketCreate, recvbuf, strlen(recvbuf), 0);
if (iResult > 0)
{
if (recvbuf[0] == '1' && recvbuf[1] == '5')
{
keepGoing = true;
continue;
}
}
} while (!keepGoing);
}
}
else if (iResult == 0)
printf("Connection closed\n");
else
printf("recv failed with error: %d\n", WSAGetLastError());
}
printf("Bytes Sent: %ld\n", iResult);
// shutdown the connection since no more data will be sent
iResult = shutdown(socketCreate, SD_SEND);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed with error: %d\n", WSAGetLastError());
closesocket(socketCreate);
WSACleanup();
return 1;
}
// cleanup
closesocket(socketCreate);
WSACleanup();
cin.get();
system("pause");
return 0;
}
server:
#include <iostream>
#include <winsock2.h>
#include <string>
#include <windows.h>
#pragma comment(lib,"ws2_32.lib")
#define MAX_NUMBER_OF_PLAYERS 1
#define BUFFER_SIZE 1024
#define LIMIT 1
// server side
#define INVALID_MOVE 00
#define PLEASE_ENTER_A_MOVE 15
#define PRINT_BOARD 20
#define END_GAME 30
// client side
#define MOVE 10
using namespace std;
int main()
{
WSADATA WsaDat;
SOCKET clientsock[2];
int minsock = 0;
int numsocks = MAX_NUMBER_OF_PLAYERS;
if (WSAStartup(MAKEWORD(2, 2), &WsaDat) != 0)
{
std::cout << "WSA Initialization failed!\r\n";
WSACleanup();
system("PAUSE");
return 0;
}
SOCKET serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (serverSocket == INVALID_SOCKET)
{
std::cout << "Socket creation failed.\r\n";
WSACleanup();
system("PAUSE");
return 0;
}
SOCKADDR_IN serverInf;
serverInf.sin_family = AF_INET;
serverInf.sin_addr.s_addr = INADDR_ANY;
serverInf.sin_port = htons(8888);
if (bind(serverSocket, (SOCKADDR*)(&serverInf), sizeof(serverInf)) == SOCKET_ERROR)
{
std::cout << "Unable to bind socket!\r\n";
WSACleanup();
system("PAUSE");
return 0;
}
listen(serverSocket, 5);
clientsock[0] = accept(serverSocket, NULL, NULL);
cout << "Client 1 has connected." << endl;
clientsock[1] = accept(serverSocket, NULL, NULL);
cout << "Client 2 has connected." << endl;
for (int i = 0; i < 2; i++)
{
cout << clientsock[i] << endl;
}
// If iMode!=0, non-blocking mode is enabled.
u_long iMode = 1;
ioctlsocket(serverSocket, FIONBIO, &iMode);
char client1_buffer[BUFFER_SIZE];
char client2_buffer[BUFFER_SIZE];
char* clientBuffer;
// until there isn't a mate.
bool gameRunning = true;
// user represents if it's user1 (0), or user2(1)
bool user = 0;
while (gameRunning)
{
if (!user)
clientBuffer = client1_buffer;
else
clientBuffer = client2_buffer;
int in = recv(clientsock[0], client1_buffer, 0, 0);
cout << in << endl;
if (in > 0)
{
// CHECKS
// MOVE COMMAND
// IF worked, send the board to both clients. if current user = 1 ==> do user to 0 | if the user = 0 => do user to 11
// ELSE, send the current client (clientsock[user]) Error message and ask for a command again.
cout << client1_buffer << endl;
cout << " IN RECV";
char* szMessage = "15";
send(clientsock[0], szMessage, strlen(szMessage), 0);
}
else if (in == 0)
{
// The connection has closed.
// REMEMBER : SAVE THE GAME SITUATION.
}
else
{
printf("recv failed: %d\n", WSAGetLastError());
// SEND ERROR MESSAGE TO BOTH CLIENTS
}
}
// Shutdown our socket
shutdown(serverSocket, SD_SEND);
// Close our socket entirely
closesocket(serverSocket);
WSACleanup();
system("pause");
return 0;
}
What Hans said. plus this:
int in = recv(clientsock[0], client1_buffer, 0, 0);
Your probably want to say this:
int in = recv(clientsock[0], client1_buffer, BUFFER_SIZE, 0);
Also, you are making a fundamental error that a lot of people make with sockets. You are assuming that your recv call on your server will return as many bytes was passed to the corresponding send call by the client. Fragmentation, segmentation, and other network stuff may cause you to receive only a partial amount of the message that was sent on the other node's send call. (Hence, TCP is a stream protocol as they say).
You should diligently check the return value from recv. Write your code as if the sender was only to going to send 1 byte at a time. You should put delimiters between your messages (a null char is fine) and loop on recv until you get a complete message. Otherwise, what seems to work fine on your own PC and on the local subnet will have strange bugs when deployed to the internet.
In the server file change
int in = recv(clientsock[0], client1_buffer, 0,0);
to
int in = recv(clientsock[0], client1_buffer, 1024,0);
change is the length of the date to be received
The problem is
strlen(recvbuf)
You probably mean
sizeof(recvbuf)
strlen(recvbuf) does not makes sense before you received the data, because your buffer contains just garbage, thus strlen() is just a bad random number generator. strlen(recvbuf) would make sense after you received the data if you would have made sure it was filled with 0. That not being the case, you can use the return value of recv() to find out how many bytes you received.
I am rather new to C++ and have run into a problem, when I connect to the server(using a browser) it sends a response fine and it shows up fine on the browser, however looking at the console it sent the webpage twice, a page view counter confirms this, from testing i am unsure of the order it runs.
loop listening for new connections:
while (true){
//create temp scoket for cconnetcion
SOCKET ClientSocket;
ClientSocket = INVALID_SOCKET;
// Accept the socket from the client when it tries to connect
ClientSocket = accept(ListenSocket, NULL, NULL);
printf("NEWCON" );
if (ClientSocket == INVALID_SOCKET) {
printf("accept failed: %d\n", WSAGetLastError());
std::string blah;
std::cin >> blah;
closesocket(ListenSocket);
WSACleanup();
return 104;
}
views += 1;
AfxBeginThread(RequestProsorses, (LPVOID)ClientSocket);
}
RequestProsorses function:
UINT RequestProsorses(LPVOID pParam){
printf("\n NEWREC");
SOCKET ClientSocket = (SOCKET)pParam;
#define DEFAULT_BUFLEN 512
char recvbuf[DEFAULT_BUFLEN];
int conResult, iSendResult;
int recvbuflen = DEFAULT_BUFLEN;
std::string returnVal = "HTTP/1.x 200 OK \n Transfer-Encoding: chunked \n\n <html><body><b>Total Page Views:</b>";
conResult = recv(ClientSocket, recvbuf, recvbuflen, 0);
if (conResult > 0) {
printf("Bytes received: %d\n", conResult);
//create response to user
returnVal += std::to_string(views) + "</body></html>";
//printf(returnVal.c_str());
// Send Responce to user
iSendResult = send(ClientSocket, returnVal.c_str(), returnVal.length(), 0);
if (iSendResult == SOCKET_ERROR) {
//printf("send failed: %d\n", WSAGetLastError());
std::string blah;
std::cin >> blah;
closesocket(ClientSocket);
WSACleanup();
}
printf("Bytes sent: %d\n", iSendResult);
}
else if (conResult == 0){
printf("Connection closing...\n");
}
else {
printf("recv failed: %d\n", WSAGetLastError());
std::string blah;
std::cin >> blah;
closesocket(ClientSocket);
WSACleanup();
}
// shutdown the send half of the connection since no more data will be sent
conResult = shutdown(ClientSocket, SD_SEND);
if (conResult == SOCKET_ERROR) {
printf("shutdown failed: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
}
closesocket(ClientSocket);
return 0;
}
Console output(form one view only):
NEWCONNEWCON
NEWREC
NEWRECBytes recived: 373
Bytes sent: 99
Bytes recevied: 287
Bytes sent:99
Hope that's enough info for you, if not i am happy to post more of course.
if statement to check foe end of header
for (int i = 0; i <= recvbuflen; i++){
if (recvbuf[i] == '\n' && (int)recvbuf[i + 1] == -52){
finished = true;
}
}
I have found the answer :), thanks to #JoachimPileborg and #MartinJames for there help!
Simply the browser was sending a second request and as the program does not check what page is being viewed(it simply sends the same page no matter what at the moment), it looked to me like it was doing the same thing twice just for one page request. the browser was trying to assess /favicon.ico just like its supposed too.
I have made changes to the code and although is by no means finished it works so here is the code if anyone's interested in the changes i made(in case there where other errors i fixed without realizing).
// HTMLtest.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <stdio.h>
#include <string>
#include <iostream>
#include <thread>
#include <afxwin.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment(lib, "Ws2_32.lib")
int views = 0;
UINT RequestProsorses(LPVOID pParam){
printf("\n NEWREC");
SOCKET ClientSocket = (SOCKET)pParam;
#define DEFAULT_BUFLEN 512
char recvbuf[DEFAULT_BUFLEN];
int conResult, iSendResult;
int recvbuflen = DEFAULT_BUFLEN;
std::string returnVal = "HTTP/1.x 200 OK \n Transfer-Encoding: chunked \n\n <html><body><b>Total Page Views:</b>";
bool finished = false;
do {
std::cout << "b";
conResult = recv(ClientSocket, recvbuf, recvbuflen, 0);
for (int i = 0; i <= recvbuflen; i++){
if (recvbuf[i] == '\n' && (int)recvbuf[i + 1] == -52){
finished = true;
}
}
if (conResult > 0) {
}
else if (conResult == 0){
printf("Connection closing...\n");
}
else {
printf("recv failed: %d\n", WSAGetLastError());
std::string blah;
std::cin >> blah;
closesocket(ClientSocket);
}
} while (conResult > 0 && finished == false);
printf("Bytes received: %d\n", conResult);
std::cout << "RECIVED: " << recvbuf;
//create response to user
returnVal += std::to_string(views) + "</body></html>";
//printf(returnVal.c_str());
// Send Responce to user
iSendResult = send(ClientSocket, returnVal.c_str(), returnVal.length(), 0);
if (iSendResult == SOCKET_ERROR) {
printf("send failed: %d\n", WSAGetLastError());
std::string blah;
std::cin >> blah;
closesocket(ClientSocket);
}
printf("Bytes sent: %d\n", iSendResult);
closesocket(ClientSocket);
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
WSADATA wsaData;
// Initialize Winsock
int IPresult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (IPresult != 0) {
printf("WSAStartup failed: %d\n", IPresult);
return 1;
}
struct addrinfo *result = NULL, *ptr = NULL, params;
ZeroMemory(¶ms, sizeof(params));
params.ai_family = AF_INET;
params.ai_socktype = SOCK_STREAM;
params.ai_protocol = IPPROTO_TCP;
params.ai_flags = AI_PASSIVE;
//resolve the IP address and port to used by the server
IPresult = getaddrinfo(NULL, "80", ¶ms, &result);
if (IPresult != 0) {
printf("getaddrinfo failed: %d\n", IPresult);
std::string blah;
std::cin >> blah;
WSACleanup();
return 100;
}
SOCKET ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if (ListenSocket == INVALID_SOCKET) {
printf("Error at socket(): %ld\n", WSAGetLastError());
std::string blah;
std::cin >> blah;
freeaddrinfo(result);
WSACleanup();
return 101;
}
// Setup the socket for HTTP
IPresult = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen);
if (IPresult == SOCKET_ERROR) {
printf("bind failed with error: %d\n", WSAGetLastError());
std::string blah;
std::cin >> blah;
freeaddrinfo(result);
closesocket(ListenSocket);
WSACleanup();
return 102;
}
//Free the memory allocated by "getadderinfo" as its no longe needed
freeaddrinfo(result);
if (listen(ListenSocket, SOMAXCONN) == SOCKET_ERROR) {
printf("Listen failed with error: %ld\n", WSAGetLastError());
std::string blah;
std::cin >> blah;
closesocket(ListenSocket);
WSACleanup();
return 103;
}
while (true){
//create temp scoket for cconnetcion
SOCKET ClientSocket;
ClientSocket = INVALID_SOCKET;
// Accept the socket from the client when it tries to connect
ClientSocket = accept(ListenSocket, NULL, NULL);
printf("NEWCON" );
if (ClientSocket == INVALID_SOCKET) {
printf("accept failed: %d\n", WSAGetLastError());
std::string blah;
std::cin >> blah;
closesocket(ListenSocket);
WSACleanup();
return 104;
}
views += 1;
AfxBeginThread(RequestProsorses, (LPVOID)ClientSocket);
}
// cleanup
//closesocket(ClientSocket);
WSACleanup();
return 0;
}
Sorry for how untidy it is :/
My question is about this previous question (unfortunely, the answer doesn't work for me): https://stackoverflow.com/questions/20314524/c-opencv-image-sending-through-socket
After get the image, the code shows only a grey picture. Am I doing the correct image handling when sending and receive the image?
Sender and receiver codes:
Image sender:
#undef UNICODE
#define WIN32_LEAN_AND_MEAN
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <opencv2/objdetect/objdetect.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
// Need to link with Ws2_32.lib
#pragma comment (lib, "Ws2_32.lib")
// #pragma comment (lib, "Mswsock.lib")
#define DEFAULT_BUFLEN 512
#define IMG_BUFLEN 1243897
#define DEFAULT_PORT "27015"
using namespace std;
using namespace cv;
int 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];
unsigned char * imgbuf;
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(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);
// Receive until the peer shuts down the connection
do {
iResult = recv(ClientSocket, recvbuf, recvbuflen, 0);
if (iResult > 0) {
printf("SERVER - bytes: %d\n", iResult);
//char * temp = (char *) malloc(9); memcpy(temp,recvbuf,8);
if (strcmp(recvbuf, "ASK"))
{
int retTamImg;
Mat captureFrame;
int imgSize = 0;
VideoCapture captureDevice;
captureDevice.open(0);
if(!captureDevice.isOpened() )
{
printf("Nao pode ler o video");
getchar();
}
captureDevice>>captureFrame;
//---------------- SEND IMAGE ----------------//
if (captureFrame.data != NULL)
{
retTamImg = captureFrame.total() * captureFrame.elemSize();
iSendResult = send( ClientSocket, (const char *) captureFrame.data, retTamImg, 0 );
if (iSendResult == SOCKET_ERROR) {
printf("resposta de pedido de face falhou. erro: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
else
printf("resposta de pedido de face enviada com suceso. Bytes: %d\n", iSendResult);
}
//FECHA CAMERA
captureDevice.release();
}
}
else if (iResult == 0)
printf("Connection closing...\n");
else {
printf("recv failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
getchar();
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();
getchar();
return 1;
}
// cleanup
closesocket(ClientSocket);
WSACleanup();
return 0;
}
Image receiver:
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
#include <opencv2/core/core.hpp>
#include <opencv2/objdetect/objdetect.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
// 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 IMG_BUFLEN 1243897
#define DEFAULT_PORT "27015"
using namespace std;
using namespace cv;
int __cdecl main(int argc, char **argv)
{
WSADATA wsaData;
SOCKET ConnectSocket = INVALID_SOCKET;
struct addrinfo *result = NULL,
*ptr = NULL,
hints;
char sendbuf [DEFAULT_BUFLEN];
char recvbuf[DEFAULT_BUFLEN];
char * imgbuf;
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);
getchar();
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();
getchar();
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();
getchar();
return 1;
}
//----------------- ASK FOR THE IMAGE ----------------------//
strncpy(sendbuf, "ASK", 8);
// Send an initial buffer
iResult = send( ConnectSocket, sendbuf, (int)strlen(sendbuf), 0 );
if (iResult == SOCKET_ERROR) {
printf("send ASK FACE failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
getchar();
return 1;
}
printf("ASK FACE SENT Bytes Sent: %ld\n", iResult);
//----------------- GET THE IMAGE ----------------------//
Mat img = Mat::zeros( 480,640, CV_8UC3);
int imgSize = (int) (img.total()*img.elemSize());
char * sockData;
sockData = (char *) malloc (sizeof(char) * imgSize + 1);
for (int i = 0; i < imgSize; i += iResult)
{
iResult = recv(ConnectSocket, sockData +i, imgSize - i, 0);
if ( iResult > 0 )
printf("CLIENTE - retorno do ASK FACE (%d/%d)- Bytes received: %d\n", i, imgSize, iResult);
else if ( iResult == 0 )
printf("CLIENTE - retorno do ASK FACE - Connection closed\n");
else
printf("CLIENTE - retorno do ASK FACE - error: %d\n", WSAGetLastError());
}
// Assign pixel value to img
int iptr=0;
for (int i = 0; i < img.rows; i++) {
for (int j = 0; j < img.cols; j++) {
img.at<cv::Vec3b>(i,j) = Vec3b(sockData[iptr+ 0],sockData[iptr+1],sockData[iptr+2]);
iptr=iptr+3;
}
}
namedWindow("outputCapture", 1);
imshow("outputCapture", img);
// imwrite("C:\\Users\\USUARIO\\Documents\\VISAO\\servidor_imagens_cam\\imagem_salva.jpg",img);
// 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();
getchar();
return 0;
}
After some time here with your code, i finally found the error. You have to use waitkey() and not getchar(). Besides this, the program it's running fine.