#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.
Related
I have a UDP server-client system that works correctly. I want to create a single function that takes in input for both UDP and TCP connection sockets and these connections should be able to take input concurrently. Previously I worked with pthreads in C and I only know how to pass some tasks to specific functions(don't know how to do these tasks concurrently in the same function). Could you please provide a very simple example of a function that can run TCP client and UDP client concurrently?
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 );
}
#include <stdio.h> // Default System Calls
#include <stdlib.h> // Needed for OS X
#include <string.h> // Needed for Strlen
#include <sys/socket.h> // Needed for socket creating and binding
#include <netinet/in.h> // Needed to use struct sockaddr_in
#include <time.h> // To control the timeout mechanism
#include <unistd.h>
#define EXPR_SIZE 1024
#define BUFLEN 512
#define TRUE 1
#define SERVERLEN 1024
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 );
}
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;
}
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.
I want to understand more about sending data over internet.
I have been searching A LOT everywhere but nothing helped...
I'm using MinGw and please dont say that i have to change my developer program.
So far i made this from what I found:
And it work great but only for my local network. Can anyone tell me how i can do the same thing only over the internet?
using namespace std;
#pragma once
#include <iostream>
#include "WinSock2.h"
const int STRLEN = 256;
class Socket
{
protected:
WSADATA wsaData;
SOCKET mySocket;
SOCKET myBackup;
SOCKET acceptSocket;
sockaddr_in myAddress;
public:
Socket();
~Socket();
bool SendData( char* );
bool RecvData( char*, int );
void CloseConnection();
void GetAndSendMessage();
};
class ServerSocket : public Socket
{
public:
void Listen();
void Bind( int port );
void StartHosting( int port );
};
class ClientSocket : public Socket
{
public:
void ConnectToServer( const char *ipAddress, int port );
};
Socket::Socket()
{
if( WSAStartup( MAKEWORD(2, 2), &wsaData ) != NO_ERROR )
{
cerr<<"Socket Initialization: Error with WSAStartup\n";
system("pause");
WSACleanup();
exit(10);
}
//Create a socket
mySocket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
if ( mySocket == INVALID_SOCKET )
{
cerr<<"Socket Initialization: Error creating socket"<<endl;
system("pause");
WSACleanup();
exit(11);
}
myBackup = mySocket;
}
Socket::~Socket()
{
WSACleanup();
}
bool Socket::SendData( char *buffer )
{
send( mySocket, buffer, strlen( buffer ), 0 );
return true;
}
bool Socket::RecvData( char *buffer, int size )
{
int i = recv( mySocket, buffer, size, 0 );
buffer[i] = '\0';
return true;
}
void Socket::CloseConnection()
{
//cout<<"CLOSE CONNECTION"<<endl;
closesocket( mySocket );
mySocket = myBackup;
}
void Socket::GetAndSendMessage()
{
char message[STRLEN];
cin.ignore();//without this, it gets the return char from the last cin and ignores the following one!
cout<<"Send > ";
cin.get( message, STRLEN );
SendData( message );
}
void ServerSocket::StartHosting( int port )
{
Bind( port );
Listen();
}
void ServerSocket::Listen()
{
//cout<<"LISTEN FOR CLIENT..."<<endl;
if ( listen ( mySocket, 1 ) == SOCKET_ERROR )
{
cerr<<"ServerSocket: Error listening on socket\n";
system("pause");
WSACleanup();
exit(15);
}
//cout<<"ACCEPT CONNECTION..."<<endl;
acceptSocket = accept( myBackup, NULL, NULL );
while ( acceptSocket == SOCKET_ERROR )
{
acceptSocket = accept( myBackup, NULL, NULL );
}
mySocket = acceptSocket;
}
void ServerSocket::Bind( int port )
{
myAddress.sin_family = AF_INET;
myAddress.sin_addr.s_addr = inet_addr( "0.0.0.0" );
myAddress.sin_port = htons( port );
//cout<<"BIND TO PORT "<<port<<endl;
if ( bind ( mySocket, (SOCKADDR*) &myAddress, sizeof( myAddress) ) == SOCKET_ERROR )
{
cerr<<"ServerSocket: Failed to connect\n";
system("pause");
WSACleanup();
exit(14);
}
}
void ClientSocket::ConnectToServer( const char *ipAddress, int port )
{
myAddress.sin_family = AF_INET;
myAddress.sin_addr.s_addr = inet_addr( ipAddress );
myAddress.sin_port = htons( port );
//cout<<"CONNECTED"<<endl;
if ( connect( mySocket, (SOCKADDR*) &myAddress, sizeof( myAddress ) ) == SOCKET_ERROR )
{
cerr<<"ClientSocket: Failed to connect\n";
system("pause");
WSACleanup();
exit(13);
}
}
int main()
{
int choice;
int port = 666;
//char *ipAddress = "127.0.0.1";
string ipAddress;
bool done = false;
char recMessage[STRLEN];
char sendMessage[STRLEN];
cout<<"1) Host server"<<endl;
cout<<"2) Join server"<<endl;
cout<<"3) Quit"<<endl;
cin>>choice;
if ( choice == 3 )
exit(0);
else if ( choice == 2 )
{
//Client
cout<<"Enter an IP address, 127.0.0.1 is the loopback address"<<endl;
cin>>ipAddress;
ClientSocket sockClient;
cout<<"ATTEMPTING TO CONNECT..."<<endl;
sockClient.ConnectToServer( ipAddress.c_str(), port );
//Connected
while ( !done )
{
sockClient.GetAndSendMessage();
cout<<"\t--WAIT--"<<endl;
sockClient.RecvData( recMessage, STRLEN );
cout<<"Recv > "<<recMessage<<endl;
if ( strcmp( recMessage, "end" ) == 0 ||
strcmp( sendMessage, "end" ) == 0 )
{
done = true;
}
}
sockClient.CloseConnection();
}
else if ( choice == 1 )
{
//SERVER
ServerSocket sockServer;
cout<<"HOSTING..."<<endl;
sockServer.StartHosting( port );
//sockServer.StartHosting( port );
//Connected
while ( !done )
{
cout<<"\t--WAIT--"<<endl;
sockServer.RecvData( recMessage, STRLEN );
cout<<"Recv > "<<recMessage<<endl;
sockServer.GetAndSendMessage();
if ( strcmp( recMessage, "end" ) == 0 || strcmp( sendMessage, "end" ) == 0 )
{
done = true;
}
}
}
}
Thanks to all who responded but, you gave me a lot to read when i just asked what part of the code should be changed so i can use the internet. Obviously I cant understand half of what is written there. Still nothing helped.
If you want to use sockets over the internet and you want your application to be usable on every network setting, including NAT, you will have to use a TCP Holepunch called technique (or UDP holepunching may also fit). I think your approach is not working
because there is some NAT between your endpoints, so socket connections fail.
I suggest to investigate on NAT. Peer-to-Peer Communication Across Network Address Translators
And this discussion here on SO
What is it that you don't understand? I see the code and it's binding to a local socket and then you connect to it with a client. You can do this over the internet as well but what is it that you aren't understanding about the process? I'm afraid you may need to start learning the basics of TCP/IP before trying to write socket code. It's like trying to start out learning engineering by building a space shuttle.
The ability to host a service that's visible from the Internet is very dependent on the type of the Internet connection you've got. If you're behind a NAT, you'll need to set up a NAT port forwarding. If your IP address is dynamic, you'll need to know your publicly available IP address (try http://www.whatismyip.com/).
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.