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;
}
Related
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 );
}
I have a client(c++) / server(c) program and currently I'm having difficulty communicating between them (I can't see what the client says on the server and vice versa). Also I am trying have this project multi-threaded, or at least accept multiple connections from clients. All help is greatly appreciated here is the code pertaining to chatting, you can view it in its entirety here
client:
recv(sockfd , server_reply , 2000 , 0);
puts("Enter message :"); // asking for password
scanf("%s" , message);
send(sockfd , message , strlen(message) , 0);
recv(sockfd, server_reply, 2000, 0);
//Receive a reply from the server
if( recv(sockfd , server_reply , 2000 , 0) < 0)
{
puts("recv failed");
}
while( (read_size = recv(nsockfd , server_reply , 4000 , 0)) != 0)
{
puts("Enter message :"); // asking for password
scanf("%s" , message);
send(sockfd , message , strlen(message) , 0);
recv(sockfd, server_reply, 2000, 0);
}
Server
char client_address[90];
sprintf(client_address, "Welcome %s", inet_ntoa(addr_remote.sin_addr));
char welc_msg[90] = "Welcome %s";
char friend_msg[50] = "Hello little friend \n";
char username[30] = "Enter user:";
char pass[30] = "Enter pass: ";
write(nsockfd , client_address , strlen(client_address)); // attempting to send client "Hello, (their ip address)"
read_size = recv(nsockfd , client_message , 4000 , 0);
read_size = recv(nsockfd , client_message , 4000 , 0);
printf( "%s", client_message);
printf( "\n");
//Receive a message from client
while( 1 ) // while( (read_size = recv(nsockfd , client_message , 4000 , 0)) != 0)
{
//clearing buffer
memset(client_message, 0, sizeof(client_message));
//taking received message and printing it
read_size = recv(nsockfd , client_message , 4000 , 0);
printf( "%s", client_message);
printf( "\n");
//Send the message back to client
// write(nsockfd , server_message , strlen(server_message));
if (strcmp(client_message , "Hello")) // condition for project
{
write(nsockfd, friend_msg, strlen(friend_msg));
}
}
When you call the system functions, always check for errors! Where relevant, also check for partial writes / receives. For example, when you have this line:
send(sockfd , message , strlen(message) , 0);
You should have something like this (untested, so think it through yourself):
(Edit: removed unnecessary resend loop to simplify code. See edit history if you want to see it...)
int msglen = strlen(message);
fprintf(stderr, "debug: about to send %d bytes", msglen);
int sent = send(sockfd , message , msglen , 0);
if (sent == -1) { // for each function, read docs for error result
perror("send message");
// do some error handling
} else if (sent < msglen) {
fprintf(stderr, "debug: partial send %d/%d\n", sent, msglen);
// do some disconnect handling
}
Once you have proper error reporing, and if you can't solve your problem with that, then update the question with this debug/error information.
Try this code:
Server.c
while (1) {
//---- ACCEPT connection ------------------------------------
sa = accept(s, 0, 0); // block for connection request
if (sa < 0) {
printf("accept error %ld ", WSAGetLastError() );
WSACleanup();
return false;
}
else {
printf("connection accepted");
}
/* gets(buf);
bytesSent = send( s, buf, 10, 0 );
printf( "Bytes Sent: %ld \n", bytesSent );*/
//------------------------------------------------------------
// Socket is now set up and bound. Wait for connection and process it.
//---- RECV bytes --------------------------------------------
bytesRecv = recv( sa, recvbuf, 10, 0 );
err = WSAGetLastError( );// 10057 = A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call)
if ( bytesRecv == 0 || bytesRecv == WSAECONNRESET ) {
printf( "Connection Closed.\n");
WSACleanup();
}
printf( "\nBytes Recv from Client: %s \n ", recvbuf );
//-------------------------------------------------------------
// if(bytesRecv != 0 || bytesRecv != WSAECONNRESET){
bytesSent = send( sa, buf, 10, 0 );
if(bytesSent == -1)
{
//break;
puts("Error\n");
}
else
{
printf( "Bytes Sent: %ld \n", bytesSent );
Sleep(1000);
}
closesocket( sa );
}
Client.c
while(1) {
//--- INITIALIZATION -----------------------------------
wVersionRequested = MAKEWORD( 1, 1 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 ) {
printf("WSAStartup error %ld", WSAGetLastError() );
WSACleanup();
return false;
}
//------------------------------------------------------
//---- Build address structure to bind to socket.--------
target.sin_family = AF_INET; // address family Internet
target.sin_port = htons (SERVER_PORT); //Port to connect on
target.sin_addr.s_addr = inet_addr (IPAddress); //Target IP
//--------------------------------------------------------
// ---- create SOCKET--------------------------------------
s = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); //Create socket
if (s == INVALID_SOCKET)
{
printf("socket error %ld" , WSAGetLastError() );
WSACleanup();
return false; //Couldn't create the socket
}
//---------------------------------------------------------
//---- try CONNECT -----------------------------------------
if (connect(s, (SOCKADDR *)&target, sizeof(target)) == SOCKET_ERROR)
{
printf("connect error %ld", WSAGetLastError() );
WSACleanup();
return false; //Couldn't connect
}
//-----------------------------------------------------------
//---- SEND bytes -------------------------------------------
bytesSent = send( s, buf, 10, 0 );
printf( "Bytes Sent: %ld \n", bytesSent );
Sleep(1000);
if((bytesRecv = recv( s, recvbuf, 10, 0 )) == SOCKET_ERROR)
{
puts("Socket Error");
err = WSAGetLastError( );// 10057 = A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call)
}
else
{
if ( bytesRecv == 0 || bytesRecv == WSAECONNRESET ) {
printf( "Connection Closed.\n");
WSACleanup();
}
printf( "\nBytes Recv from Server: %s \n ", recvbuf );
//closesocket( sa );
}
//------------------------------------------------------------
closesocket( s );
WSACleanup();
}
The above code strictly for Windows.
#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.
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/).