Click here to Skip to main content
15,305,361 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more: , +
update:

Since my initial question was very specific, i would like to start of with asking how do i inititate a simple bidirectional communication using tcp/ip?



Hello,
I want to receive H.264 video stream from a TCP/IP socket (without use of RTSP or other internet streaming protocols) from a Raspberry pi camera to my windows OS.

Previously the data was stored in a buffer and then sent to the windows side. but the cache memory fills up and i cant get continous video streaming.

Also, it would be really helpful if i could get a bidirectional connection via TCP/IP. On PC side,i want to use an easy-to-use C++ library for communication with the Raspberry Pi. The communication would consist of sending commands like “Set Camera Resolution” or “Start/Stop Grabbing” to the Raspberry Pi as well as of receiving and decoding of grabbed images. The library should be portable at least for MS Windows and Linux.

I am currently designing the code using c++ in visual studio 2012. The reason being that to make the program portable in other os, i would need minimum dependencies (c# uses .net libraries which make it tedious to configure on a linux os)>


Thank you in advance

What I have tried:

i tried the following code (from this site) using winsock2.h and WS2_32.lib. the code is unidirection between 2 windows computers. the IP adressing is static for the client.

------------------server side----------------------------------------------
#include <winsock2.h>
#include <iostream>
#include <process.h>
#include <stdio.h>
#include <tchar.h>
#include <windows.h>

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
// Initialize WinSock2.2 DLL
// low word = major, highword = minor

WSADATA wsaData = {0};
WORD wVer = MAKEWORD(2,2);
int nRet = WSAStartup( wVer, &wsaData );
if( nRet == SOCKET_ERROR )
{
// WSAGetLastError()
cout << "Failed to init Winsock library" << endl;
return -1;
}
cout << "Starting server" << endl;


// name a socket
WORD WSAEvent = 0;
WORD WSAErr = 0;

// open a socket
//
// for the server we do not want to specify a network address
// we should always use INADDR_ANY to allow the protocal stack
// to assign a local IP address

SOCKET hSock = {0};
hSock = socket( AF_INET, SOCK_STREAM, IPPROTO_IP );
if( hSock == INVALID_SOCKET )
{
cout << "Invalid socket, failed to create socket" << endl;
return -1;
}

// name socket
sockaddr_in saListen = {0};
saListen.sin_family = PF_INET;
saListen.sin_port = htons( 10000 );
saListen.sin_addr.s_addr = htonl( INADDR_ANY );

// bind socket's name
nRet = bind( hSock, (sockaddr*)&saListen, sizeof(sockaddr) );
if( nRet == SOCKET_ERROR )
{
cout << "Failed to bind socket" << endl;
//shutdown( hSock );
closesocket( hSock );
return -1;
}

while( true )
{
cout << "Listening for connections" << endl;
// listen
nRet = listen( hSock, 5 ); // connection backlog queue set to 10
if( nRet == SOCKET_ERROR )
{
int nErr = WSAGetLastError();
if( nErr == WSAECONNREFUSED )
{
cout << "Failed to listen, connection refused" << endl;
}
else
{
cout << "Call to listen failed" << endl;
}
closesocket( hSock );
return -1;
}

// connect
sockaddr_in saClient = {0};
int nSALen = sizeof( sockaddr );
SOCKET hClient = accept( hSock, (sockaddr*)&saClient, &nSALen );
if( hClient == INVALID_SOCKET )
{
cout << "Invalid client socket, connection failed" << endl;
closesocket( hSock );
return -1;
}
cout << "Connection estabilished" << endl;

// process data
char wzRec[512] = {0};
int nLeft = 512;
int iPos = 0;
int nData = 0;
do
{
nData = recv( hClient, &wzRec[iPos], nLeft, 0 );
if( nData == SOCKET_ERROR )
{
cout << "Error receiving data" << endl;
memset( &wzRec, 0, sizeof( wzRec ) );
break;
}
nLeft -= nData;
iPos += nData;
} while( nLeft > 0 );

cout << "Data Recieved: " << wzRec << endl;

// echo data back to client

iPos = 0;
nLeft = 512;

do
{

nData = send( hClient, &wzRec[iPos], nLeft, 0 );
if( nData == SOCKET_ERROR )
{
cout << "Error sending data" << endl;
break;
}
nLeft -= nData;
iPos += nData;
} while( nLeft > 0 );

// close client connection
closesocket( hClient );
hClient = 0;
// perform a lowercase comparison
if( _stricmp( wzRec, "!shutdown" ) == 0 )
{
break;
}
// clear data buffer
memset( &wzRec, 0, sizeof( wzRec ) );
} // loop

cout << "Shutting down the server" << endl;

// close server socket
nRet = closesocket( hSock );
hSock = 0;
if( nRet == SOCKET_ERROR )
{
cout << "Error failed to close socket" << endl;
}
// Release WinSock DLL
nRet = WSACleanup();
if( nRet == SOCKET_ERROR )
{
cout << "Error cleaning up Winsock Library" << endl;
return -1;
}
cout << "Server is offline" << endl;
return 0;
}


---------------------client side------------------------------------



#include <winsock2.h>
#include <iostream>
#include <stdio.h>
//#include <tchar.h>
#include <windows.h>
#include <conio.h>
using namespace std;
int main(int argc, char* argv[])
{
// Initialize WinSock2.2 DLL
// low word = major, highword = minor

WSADATA wsaData = {0};
WORD wVer = MAKEWORD(2,2);
int nRet = WSAStartup( wVer, &wsaData );
if( nRet == SOCKET_ERROR )
{
cout << "Failed to init Winsock library" << endl;
return -1;
}

cout << "Opening connection to server" << endl;
WORD WSAEvent = 0;
WORD WSAErr = 0;
SOCKET hServer = {0};

// open a socket
//
// for the server we do not want to specify a network address
// we should always use INADDR_ANY to allow the protocal stack
// to assign a local IP address
hServer = socket( AF_INET, SOCK_STREAM, IPPROTO_IP );
if( hServer == INVALID_SOCKET )
{
cout << "Invalid socket, failed to create socket" << endl;
return -1;
}

// name a socket
sockaddr_in saServer = {0};
saServer.sin_family = PF_INET;
saServer.sin_port = htons( 10000 );
//saServer.sin_addr.s_addr = inet_addr( "127.0.0.1" );
saServer.sin_addr.s_addr = inet_addr( "172.16.26.32" );

// connect
nRet = connect( hServer, (sockaddr*)&saServer, sizeof( sockaddr ) );
if( nRet == SOCKET_ERROR )
{
cout << "Connection to server failed" << endl;
closesocket( hServer );
return -1;
}

cout << "Connected to server" << endl;
cout << "Sending data to server" << endl;

// process data

char wzRec[1024] = "Hello from client no 1!!!";
int nLeft = 512;
int iPos = 0;
int nData = 0;

if( argc == 2 )
{
// copy input string from command argument
strcpy_s( wzRec, 1024, argv[1] );
}

do
{
nData = send( hServer, &wzRec[iPos], nLeft, 0 );

if( nData == SOCKET_ERROR )
{
cout << "Error sending data" << endl;
break;
}
nLeft -= nData;
iPos += nData;
} while( nLeft > 0 );
// clear data buffer

memset( &wzRec, 0, sizeof( wzRec ) );
nLeft = 512;
iPos = 0;
do
{
nData = recv( hServer, &wzRec[iPos], nLeft, 0 );
if( nData == SOCKET_ERROR )
{
cout << "Error receiving data" << endl;
break;
}
nLeft -= nData;
iPos += nData;
} while( nLeft > 0 );

cout << "Data Echoed: " << wzRec << endl;
cout << "Closing connection" << endl;

// shutdown socket
nRet = shutdown( hServer, SD_BOTH );
if( nRet == SOCKET_ERROR )
{
// WSAGetLastError()
cout << "Error trying to perform shutdown on socket" << endl;
return -1;
}
// close server socket
nRet = closesocket( hServer );
hServer = 0;

if( nRet == SOCKET_ERROR )
{
cout << "Error failed to close socket" << endl;
}

// Release WinSock DLL
nRet = WSACleanup();
if( nRet == SOCKET_ERROR )
{
cout << "Error cleaning up Winsock Library" << endl;
return -1;
}
cout << "Data sent successfully" << endl;
return 0;
getch;
}
Posted
Updated 30-Apr-16 4:41am
v2
Comments
Jochen Arndt 21-Mar-16 6:01am
   
The code snippets are showing a basic TCP client server communication.

I suggest to split your communication in two parts:
- A control channel to send commands (and receive responds)
- A streaming channel

The first can be implemented based on the code snippets where the Pi is the server and the PC the client.

For the second the PC opens a listening socket and process incoming data which are send by the Pi when an appropriate start command has been send using the control channel.

So you should start implementing the above and come back if you have specific problems with your code. Your actual question is far too comprehensive for being a "Quick Answer".

[EDIT]
While the control channel should be a TCP connection the streaming channel might be an UDP connection.
[/EDIT]
Arthur V. Ratz 22-Mar-16 0:46am
   
+5.
violence666 22-Mar-16 4:43am
   
i didnt get the solution you mentioned. :)

1 solution

The easiest way to start playing with this is grab telnet code its everywhere on the net in all flavours.

Windows has both telnet server and client options standard you go to "install options" and you can choose either. You can therefore play with writing the client or server code and have the opposite just running on your local machine to play around. The local host IP is 127.0.0.1 for your machine always :-)

You start by being able to bidirectionally communication going from your app to the windows app.

When you have done one end, reverse the windows installation and do the other end.

Now you have both ends in your own code so now you can move to your own port address and own protocol and when you get to that point its easy to help you more because you have code we can help with.
   

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900