Receive GET request through sockets - c++

How can I receive GET request through sockets? For example I am writing in browser:
127.0.0.1:41233/?data=mymessage
and I want my application to receive "mymessage". I wrote this piece of code but recv() returns WSAENOTCONN error and I don't know how to fix it.
int main() {
WSADATA socketData;
SOCKET portListener;
struct sockaddr_in saInfo = {0};
if ( WSAStartup( MAKEWORD(1, 1), &socketData ) != 0) {
printf( "WSAStartup() error!" );
return 0;
}
portListener = socket( AF_INET, SOCK_STREAM, 0 );
if ( portListener == INVALID_SOCKET ) {
printf( "socket() error!" );
}
else {
saInfo.sin_family = AF_INET;
saInfo.sin_port = htons(41233);
saInfo.sin_addr.S_un.S_addr = inet_addr( "127.0.0.1" );
if ( bind( portListener, ( sockaddr * ) &saInfo, sizeof(saInfo)) == SOCKET_ERROR ) {
printf( "bind() error!\n" );
closesocket( portListener );
return 0;
}
if ( listen( portListener, SOMAXCONN ) == SOCKET_ERROR ) {
printf( "listen() error!\n" );
closesocket( portListener );
return 0;
}
if ( accept( portListener, NULL, NULL ) == INVALID_SOCKET ) {
printf( "accept() error!\n" );
closesocket( portListener );
return 0;
}
char buf[128];
int rcvCount;
rcvCount = recv( portListener, buf, 128, 0 );
printf( "Error: %d\n", WSAGetLastError() );
if ( rcvCount > 0 ) {
printf( "%s\n", buf );
}
closesocket( portListener );
}
WSACleanup();
return 0;
}

When accept succeeds, it returns a fresh connected socket which you should use for reading data. Now you're throwing away its return value, except a check for INVALID_SOCKET. As expected, recv doesn't work for portListener: portListener never becomes connected itself.

Related

How to write a very simple TCP server-client system where client listens for 4 byte integer data?

I extensively researched online and the examples of server-client systems on github are too complicated for me. What is the standard way of building a server-client TCP connection in cpp?
I built the UDP client-server with some help. Is there a way to modify these programs into a TCP client?
client
void UDP(){
int fd;
if ( (fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
perror("socket failed");
return 1;
}
struct sockaddr_in serveraddr;
memset( &serveraddr, 0, sizeof(serveraddr) );
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons( 50037 );
serveraddr.sin_addr.s_addr = htonl( 0x7f000001 );
for ( int i = 0; i < 4; i++ ) {
if (sendto( fd, "hello", 5, 0, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0 ) {
perror( "sendto failed" );
break;
}
printf( "message sent\n" );
}
close( fd );
}
server
int main( void )
{
int fd;
if ( (fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
perror( "socket failed" );
return 1;
}
struct sockaddr_in serveraddr;
memset( &serveraddr, 0, sizeof(serveraddr) );
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons( 50037 );
serveraddr.sin_addr.s_addr = htonl( INADDR_ANY );
if ( bind(fd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0 ) {
perror( "bind failed" );
return 1;
}
char buffer[200];
for ( int i = 0; i < 4; i++ ) {
int length = recvfrom( fd, buffer, sizeof(buffer) - 1, 0, NULL, 0 );
if ( length < 0 ) {
perror( "recvfrom failed" );
break;
}
buffer[length] = '\0';
printf( "%d bytes: '%s'\n", length, buffer );
}
close( fd );
}

use timer to close server as well as connection

Issues:
1) To close down the server say after 10 sec if request to accept connection has not come from client.
2) Also broke the connection and close the server if no packets has been received from the client say for 10 secs .
Overview : I have an application which opens RFcomm server connection and DUT( Device under test) connects to it. Once connection with Rfcomm has been established then the application creates SCO server and listen for sco connection. All I wanted is to close the server if no request for conncection has been received on RFcomm or SCO side . Also close the connection and server if DUT has failed to send any packets with 10 secs.
As pointed out by forum member to me to use KEEPALIVE but my application crashes as I think KEEPALIVE does not work with SOL_SCO.
Below are the sample code
int ScoServerListen(void( *handler )( int sco_listen_sock ) )
{
printf(" start sco_listen connection\n" );
struct sockaddr_sco addr;
struct sco_conninfo conn;
socklen_t optlen;
int sco_listen_sock, sco_accept_sock;
char ba[18];
int *new_sock;
// Create socket //
sco_listen_sock = socket( PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO );
if( sco_listen_sock < 0 )
{
printf( "Can't create socket: %s (%d)\n", strerror( errno ), errno );
exit(1);
}
printf(" start sco_listen connection .. socket created.... yeeee \n" );
// Bind to local address //
memset( &addr, 0, sizeof( addr ) );
addr.sco_family = AF_BLUETOOTH;
bacpy( &addr.sco_bdaddr, &bdaddr );
if( bind( sco_listen_sock, ( struct sockaddr * ) &addr, sizeof( addr ) ) < 0)
{
printf("Can't bind socket: %s (%d)\n", strerror(errno), errno );
goto error;
}
printf(" start sco_listen connection .. bind done.... yeeee \n" );
// Listen for connections //
if( listen( sco_listen_sock, no_of_connect_listen ) )
{
printf("Can not listen on the socket: %s (%d)\n", strerror( errno ), errno );
goto error;
}
std::cout << "Waiting for connection ...\n";
while( 1 )
{
memset(&addr, 0, sizeof(addr));
optlen = sizeof(addr);
sco_accept_sock = accept( sco_listen_sock, ( struct sockaddr * ) &addr, &optlen );
if( sco_accept_sock < 0 )
{
printf("Accept for SCO failed: %s (%d)\n", strerror( errno ), errno );
goto error;
}
//using socketoption
//Get connection information //
memset( &conn, 0, sizeof( conn ) );
optlen = sizeof( conn );
if( getsockopt( sco_accept_sock, SOL_SCO, SCO_CONNINFO, &conn, &optlen ) < 0)
{
printf( "Can't get SCO connection information: %s (%d)\n", strerror(errno), errno);
close( sco_accept_sock );
goto error;
}
ba2str( &addr.sco_bdaddr, ba );
printf( "Connect from %s [handle %d, class 0x%02x%02x%02x]",ba, conn.hci_handle, conn.dev_class[2], conn.dev_class[1], conn.dev_class[0]);
pthread_t sniffer_thread;
new_sock = (int*)malloc(1);
*new_sock = sco_accept_sock;
if( pthread_create( &sniffer_thread, NULL, connection_handler, (void*)new_sock )< 0 )
{
perror(" could not create thread");
return 1;
}
( void )pthread_join( sniffer_thread, NULL );
puts (" handler assigned");
close( sco_accept_sock );
close( sco_listen_sock );
printf( "Disconnect");
//close( sco_listen_sock );
exit(0);
}
return 0;
error:
close( sco_listen_sock );
exit( 1 );
}
void *connection_handler( void *socket_desc)
{
// get socket descriptor
int sock = *(int*)socket_desc;
int read_size;
char*message, message_client[ 200 ];
//receive messgae from client
while( read_size = recv( sock, message_client, 200, 0 ) > 0 )
{
printf(" very good\n");
}
if( read_size == 0 )
{
printf("clinet disconnected \n");
fflush( stdout);
}
else if( read_size == -1 )
{
printf("received failed \n");
perror( " recv fialed");
}
free( socket_desc );
int rel = 200;
pthread_exit(&rel);
return 0;
}
int RfcommListen( uint8_t channel )
{
printf(" rfcomm --> we are at that start\n");
int rfcomm_sock; // socket descriptor for local listener
int rfcomm_client; // socket descriptor for remote client
socklen_t len = sizeof(struct sockaddr_rc);
struct sockaddr_rc remote; // local rfcomm socket address
struct sockaddr_rc local; // remote rfcomm socket address
char pszremote[20]={ 0 };
// initialize a bluetooth socket
rfcomm_sock = socket( PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM );
if( rfcomm_sock < 0 )
{
printf( "RFComm socket Error \n" );
return BtSocketError;
}
memset(&local, 0, sizeof(local));
local.rc_family = AF_BLUETOOTH;
local.rc_bdaddr = *BDADDR_ANY_INITIALIZER;
local.rc_channel = channel;
// bind the socket to a bluetooth device
if( bind( rfcomm_sock, ( struct sockaddr * )&local, sizeof( local ) ) < 0 )
{
close( rfcomm_sock );
return BtSocketError;
}
printf(" rfcomm --> bind successful\n");
// set the listening queue length
if( listen( rfcomm_sock, 1 ) < 0 )
{
printf(" we are in SCO Configure where listen failed \n");
return BtSocketError;
}
printf("accepting connections on channel: %d\n", channel);
// accept incoming connections; this is a blocking call
rfcomm_client = accept( rfcomm_sock, (struct sockaddr *)&remote, &len );
ba2str( &remote.rc_bdaddr, pszremote );
printf("received connection from: %s\n", pszremote);
// turn off blocking
if ( fcntl( rfcomm_client, F_SETFL, O_NONBLOCK ) < 0 )
{
printf("Failed non blocking\n");
return BtSocketError;
}
// return the client socket descriptor
return rfcomm_client;
}

Sockets will just die and not reconnect after some time

I wrote this module for a chat room, and whenever the socket dies it should try to reconnect. However, I've noticed that after around 10 or 15 minutes, the socket will stop trying to reconnect. Why could this happen? My code is as follows:
bool Socket::Connection::_connect(int delay_ms)
{
closesocket(sock);
hostEntry = gethostbyname(host);
if( !hostEntry )
{
//Couldn't resolve our host
return false;
}
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if( sock == INVALID_SOCKET )
{
//Invalid socket
return false;
}
SOCKADDR_IN serverInfo;
serverInfo.sin_family = AF_INET;
serverInfo.sin_addr = *(LPIN_ADDR)*hostEntry->h_addr_list;
serverInfo.sin_port = htons(port);
int nret = SOCKET_ERROR;
while( (nret == SOCKET_ERROR) )
{
nret = connect(sock, (LPSOCKADDR)&serverInfo, sizeof(struct sockaddr));
if( nret == SOCKET_ERROR )
Sleep(delay_ms);
if( running == false )
return false;
}
return true;
}
void Socket::Connection::start()
{
u_long iMode = 1;
fd_set rdevents;
struct timeval tv;
while( 1 ) //Outer, connection loop
{
if( !_connect(RECONNECT_TIME) )
continue;
int nret = ioctlsocket(sock, FIONBIO, &iMode);
if( nret != NO_ERROR )
continue;
//if( onconnect != NULL )
//onconnect(sock);
while( 1 ) //Inner, command loop
{
FD_ZERO( &rdevents );
FD_SET( sock, &rdevents );
tv.tv_sec = 8;
tv.tv_usec = 0;
nret = select(0, &rdevents, NULL, NULL, &tv);
if( nret == SOCKET_ERROR )
{
break;
}
else if( nret > 0 )
{
if( FD_ISSET(sock, &rdevents) )
{
char buf[1024];
nret = recv(sock, buf, 1024, 0);
if( nret == 0 )
break;
if( onrecv != NULL ) onrecv(sock, buf, nret);
}
}
}
}
closesocket(sock);
}
I fail to see the code where it says 'if socket dies, reconnect'. I do see the code that says 'when I ask you to connect, try connection in a loop till that succeeds'. They are two different things. Is there something else somewhere in your code that keeps calling start() in a loop? The command loop in the start() function would be 'breaking' out on socket errors .... and I do not see any attempt to reconnect after that break out.

writing tcp server -- buffering a stream

#include <sys/socket.h> // for socket(), bind(), listen(), accept()
#include <netinet/in.h> // for PF_INET, SOCK_STREAM, IPPROTO_TCP
#include <stdio.h> // for printf(), perror()
#include <unistd.h> // for read(), write(), close()
#include <string.h> // for bzero()
#define DEMO_PORT 9723
int main( void )
{
//-----------------------------------------
// create an unnamed socket for the server
//-----------------------------------------
int sock = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP );
if ( sock < 0 )
{
perror( "opening stream socket" );
return -1;
}
printf( "\nsock=%d \n", sock );
//----------------------------------------
// construct a name for the server socket
//----------------------------------------
struct sockaddr_in self;
socklen_t nlen = sizeof self;
bzero( &self, sizeof self );
self.sin_family = AF_INET;
self.sin_port = htons( DEMO_PORT );
self.sin_addr.s_addr = htonl( INADDR_ANY );
if ( bind( sock, (sockaddr *)&self, nlen ) < 0 )
{
perror( "bind failed" );
return -1;
}
printf( "bind succeeded port: %d\n",DEMO_PORT);
//---------------------------------------------------------
// now create a connection queue and wait for some clients
//---------------------------------------------------------
if ( listen( sock, 5 ) < 0 )
{
perror( "listen failed" );
return -1;
}
printf( "listen succeeded \n" );
//---------------------------------------------------
// main loop to process clients' connection-requests
//---------------------------------------------------
while ( 1 )
{
sockaddr_in peer;
socklen_t plen = sizeof peer;
bzero( &peer, plen );
printf( "server waiting \n" );
int client = accept( sock, (sockaddr *)&peer, &plen );
if ( client < 0 ) { perror( "accept" ); break; }
//---------------------------------------------
// we can now read from or write to the client
//---------------------------------------------
char ch;
int index = 0;
char get[1024];
if ( read( client, &ch, 1 ) < 0 )
{
perror( "read" );
}
bool go = true;
while(go){
if(ch != '/' && ch != '\r'){
printf("read: %hhd\n", ch);
get[index] = ch;
printf( "got stuff: %s\n", get );
index++;
read(index, &ch, 1);
} else {
go = false;
index = 0;
close( client );
printf( "server responded, connection closed" );
}
}
//if ( write( client, &ch, 1 ) < 0 ) { perror( "write" ); break; }
}
close( sock );
printf( "\n" );
}
the while(go) look never works and it buffers incorrectly. I do not see the pattern within the buffer or how it works.
What is the correct way to do this? to except a certain amount of bytes, store them in a string, then terminate the read if it reaches a newline character?
You are passing index into the second read call where you should be passing client.
This may not be your only problem but I think it is one of them.

Setting winsock select timeout accurately

I am trying to make my accept call timeout after a specified time period and I tried following the suggestion here:
Winsock accept timeout
in which case I pass a TIMEVAL struct to select when I call it, problem is when I set tv.tv_usec to say around 40 minutes or so, the select call times out immediately instead of waiting for the 40 minutes I specified. MSDN states that the timeout for select is the maximum time that it will wait, how do I make it such that select or accept for that matter waits for a specific time period before timing out?
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <WinSock2.h>
#include <Ws2tcpip.h>
#include <cstdio>
#include <tchar.h>
VOID _tmain( int argc, TCHAR *argv[] )
{
WSADATA wsaData = { 0 };
ADDRINFOA hINTs = { 0 };
PADDRINFOA pResult = NULL;
SOCKET hServerSocket = INVALID_SOCKET,
hClientSocket = INVALID_SOCKET;
TIMEVAL tv = { 0 };
INT iReturnStatus = -1;
DWORD dwRecvTimeout = 30000, // Milliseconds
dwSendTimeout = 30000; // Milliseconds
fd_set readFDs = { 0 };
if ( WSAStartup( MAKEWORD( 2, 2 ), &wsaData ) )
{
_tprintf_s( TEXT( "WSAStartup Failed\n" ) );
return;
}
ZeroMemory( &hINTs, sizeof( hINTs ) );
hINTs.ai_family = AF_INET;
hINTs.ai_socktype = SOCK_STREAM;
hINTs.ai_protocol = IPPROTO_TCP;
hINTs.ai_flags = AI_PASSIVE;
if ( getaddrinfo( NULL, TEXT( "9001" ), &hINTs, &pResult ) )
{
WSACleanup();
_tprintf_s( TEXT( "getaddrinfo Failed\n" ) );
return;
}
if ( ( hServerSocket = socket( pResult -> ai_family, pResult -> ai_socktype, pResult -> ai_protocol ) ) == INVALID_SOCKET )
{
freeaddrinfo( pResult );
WSACleanup();
_tprintf_s( TEXT( "socket Failed\n" ) );
return;
}
int iResult = bind( hServerSocket, ( pResult -> ai_addr ), pResult -> ai_addrlen );
if ( iResult == SOCKET_ERROR )
{
freeaddrinfo( pResult );
closesocket( hServerSocket );
WSACleanup();
_tprintf_s( TEXT( "bind Failed\n" ) );
return;
}
freeaddrinfo( pResult );
if ( listen( hServerSocket, SOMAXCONN ) )
{
closesocket( hServerSocket );
WSACleanup();
_tprintf_s( TEXT( "listen Failed\n" ) );
return;
}
hClientSocket = INVALID_SOCKET;
for ( ;; )
{
tv.tv_usec = 2400000000; // microseconds
FD_ZERO( &readFDs );
FD_SET( hServerSocket, &readFDs );
_tprintf( "select()\n" );
iReturnStatus = select( 0, &readFDs, NULL, NULL, &tv );
// Select Error
if ( iReturnStatus == SOCKET_ERROR )
{
_tprintf( "select Failed\n" );
}
// Select Success
else if ( iReturnStatus )
{
// Connection Established On Server Socket
if ( FD_ISSET( hServerSocket, &readFDs ) )
{
// Accept Client Connection
hClientSocket = accept( hServerSocket, NULL, NULL );
if ( hClientSocket == INVALID_SOCKET )
{
_tprintf( "accept Failed\n" );
}
else
{
// Set Recv Timeout
setsockopt( hClientSocket, SOL_SOCKET, SO_RCVTIMEO, ( const char * ) &dwRecvTimeout, sizeof( dwRecvTimeout ) );
// Set Send Timeout
setsockopt( hClientSocket, SOL_SOCKET, SO_SNDTIMEO, ( const char * ) &dwSendTimeout, sizeof( dwSendTimeout ) );
// Process Client Request(s)
// HandleConnection( ClientSocket );
}
}
// Connection Established On Unknown Socket
else
{
_tprintf( "Invalid Socket Returned\n" );
}
}
// Select Timeout
else
{
_tprintf( "select Timeout\n" );
}
}
if ( hServerSocket != INVALID_SOCKET )
closesocket( hServerSocket );
return;
}
why is this so?
This is per defintion.
Verbatim from MSDN:
tv_sec
Time interval, in seconds.
tv_usec
Time interval, in microseconds. This value is used in combination with
the tv_sec member to represent time interval values that are not a
multiple of seconds.
The problem is with tv.tv_usec; tv_usec as per man page is of type 'long'. The value (2400000000) is out of range of long and that is the reason you are getting such select system behavior.
If you want select to wait for 40 min then make sure you are using tv.tv_sec.