Validity of a Socket - c++

I have created a socket using the following lines of code and i get a valid socket and connection is established between the client and server machines. Is there a possibility that the socket becomes invalid due to network disturbances or any other reason.
If so how do we check whether the socket is valid or not.
SOCKET SocServer;
//To Set up the sockaddr structure
ServerSock.sin_family = AF_INET;
ServerSock.sin_addr.s_addr = INADDR_ANY
ServerSock.sin_port = htons(PortNumber);//port number of 5005
// To Create a socket for listening on PortNumber
if(( SocServer = socket( AF_INET, SOCK_STREAM, 0 )) == INVALID_SOCKET )
{
return FALSE;
}
//To bind the socket with wPortNumber
if(bind(SocServer,(sockaddr*)&ServerSock,sizeof(ServerSock))!=0)
{
return FALSE;
}
// To Listen for the connection on wPortNumber
if(listen(SocServer,SOMAXCONN)!=0)
{
return FALSE;
}
I know i can check for INVALID_SOCKET which in other words means the socket is 0. Is there any other way out because my SocServer will have a value say 2500, i want to check if this socket is valid.

Pass your socket to any one of the windows socket functions (eg. getsockopt()), if the socket is invalid, it will return SOCKET_ERROR while WSAGetLastError() will return WSAENOTSOCK.
It is important to note that INVALID_SOCKET does not equal 0(the actual value, which you should not use specifically is ((SOCKET)(~0))

The socket can become "invalid" when either side (expected or unexpected) disconnects, but not out of the blue due to network interferences (unless it disconnects, read above).
You can detect this by checking the return values of send() and recv() for -1 (SOCKET_ERROR)

The socket will not go invalid. But after you listen() you must accept() a connection. That connection may be lost at some point. It could be detected by a failure to write to the socket or recv() returning with error. Then you just recycle back to listen().

First, assuming that INVALID_SOCKET (which you don't show) is actually defined as 0 this is incorrect. socket returns -1 on failure like the other system calls (0 is a valid fd that could be returned).
Then once you accept a connection, your send/write or recv/read call will return -1. If you're trying to write, errno will be set to EPIPE to indicate the socket was closed (by your client). There's no way to just ask if a socket is closed.

Related

UDP socket select() returns 1 without delay (timeout) under some conditions

I fallen into problem during development of my client application.
I want to use non-blocking UDP sockets in my application to communicate with a server. I am using winsock2 library on Windows.
But... For some reason I have strange behavior of select() function under some conditions:
Socket don't have bound address and port (it is client-side socket, so it don't need it).
Before select() I send data to my local address and some port with sendto call.
For example: 192.168.1.2
Under these conditions select() instantly (without even waiting for timeout) returns 1. Like I have some packet ready to receive.
But if call recvFrom then it will sure return -1.
If I send my packets from client to any other address (which is not my address on LAN) then select() works as intended.
Also select() works as intented if don't send any packets to any address before calling select().
Socket initialization method:
bool CUdpSocket::initialize()
{
_handle = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
... error processing code, returns false if error...
}
Method which uses select(). This method works fine for server socket (with bound address and port).
bool CUdpSocket::waitData(s32 timeout_ms)
{
fd_set readset;
int result;
struct timeval tv;
// Initialize the set.
FD_ZERO(&readset);
FD_SET(_handle, &readset);
// Initialize time out struct.
tv.tv_sec = 0;
tv.tv_usec = timeout_ms * 1000;
result = select(_handle + 1, &readset, NULL, NULL, &tv);
// Timeout with no data.
if (result == 0) {
return false; // Get out of here!
}
// Error.
if (result < 0) {
// TODO: Maybe throw exception or do something.
return false;
} else if (!FD_ISSET(_handle, &readset)) {
return false; // No data!
}
// There is some data!
return true;
}
If you send a packet from an unbound UDP socket, the OS will pick an usused port for you and bind the socket to that port -- the UDP protocol requires that the sending port have an address to send from.
So if the packet you're sending results in a response, then it makes perfect sense for the select to return 1 -- that's the response to the packet you sent.

Switching between TCP and UDP simultaneously

I am working on robot control project where I should primarily (1)send some data about speed and fixed positions to the robot then (2)start a realtime control using my PC and repeat.
I chose to use TCP/IP for the first step and for realtime UDP/IP.
I tried to code this, but I believe something is missing.
I have some problems:
1- When there is no incoming (clients) connections accept function didn't return valid socket nor Message[10] is printed!!
2- Is it ok to Sendto using the same server IP and port?
3- Is this the right way to switch between UDP and TCP back and forth or there are some considerations should be undertaken?
while(Comm_Loop)
{
while (TCP_Loop)
{
TCP_Client = accept(TCP_Server, (struct sockaddr*) &Client_Address, &Client_Address_Length) ;
if ( TCP_Client != INVALID_SOCKET)
{
if (Data_Trans)
{
State = send(TCP_Client, Msg, sizeof(Msg), 0) ;
if (State != SOCKET_ERROR)
TCP_Loop = 0 ;
else
cout << Message[8] ;
}
}
else cout << Message[10] ;
}
Check_Send = sendto(UDP_Socket,
UDP_Send_Packet,
sizeof(UDP_Send_Packet),
0,
(LPSOCKADDR) &Socket_Address,
sizeof(Socket_Address));
fd_set SockSet ;
timeval Time_Out ;
FD_ZERO(&SockSet) ;
FD_SET(UDP_Socket, &SockSet);
Time_Out.tv_sec = 5;
Time_Out.tv_usec = 0 ;
State = select(0, &SockSet, (fd_set *)NULL, (fd_set *)NULL, &Time_Out) ;
if((State > 0) && (FD_ISSET(UDP_Socket, &SockSet) != 0))
{
Check_Recieve = recvfrom(UDP_Socket,
UDP_Recieve_Packet,
Buffer_Length,
0,
NULL,
NULL);
TCP_Loop = 1 ;
}
else
{
// Reception timeout
Comm_Loop = 0;
}
}
closesocket(TCP_Client) ;
closesocket(TCP_Server) ;
closesocket(UDP_Socket) ;
WSACleanup() ;
return 0;
}
1- When there is no incoming (clients) connections accept function
didn't return valid socket nor Message[10] is printed!!
Normal behavior by accept() is to block (i.e. not return) until either an incoming TCP connection is received, or an error occurs. If you don't want accept() to block, you can set the TCP_Server socket to be non-blocking, so that instead of blocking it returns -1 and sets errno to EWOULDBLOCK instead.
As far as Message[10] not printing, keep in mind that the stdout/cout stream is buffered, which means any text you send to it won't actually show up in the Terminal window until either you've printed a newline character ('\n' or std::endl) or manually flushed the stream. So if you aren't seeing the output you expected in a timely manner, you might want to verify that your Message[10] string contains a newline character, or alternatively append << std::endl; to the end of your cout << blah calls.
2- Is it ok to Sendto using the same server IP and port?
That question is ambiguous -- same server IP and port as what?
If you are asking if you can send your UDP sockets to the same IP address and port that were set in the accept() call (i.e. Client_Address in your code), you can do that, but it will only work if your robot has set up a UDP socket to bind to that port number in the UDP port-space. (Note that a UDP socket and a TCP socket can both bind to the same port without interfering with each other since they have different port-spaces, but by the same token you won't ever see TCP-data appear on your UDP socket or vice versa)
3- Is this the right way to switch between UDP and TCP back and forth
or there are some considerations should be undertaken?
It looks like it could more or less work, although a more robust design would be one that uses non-blocking sockets and always passes all of the sockets (i.e. the original TCP socket that you pass in to accept(), the per-TCP-connection TCP socket(s) that were returned by accept(), and your UDP socket) into every select call's read-fd_set, and then always checks all of those sockets (via FD_ISSET()) after select() returns and reacts appropriately when any of them is ready-for-read. That way your program could always handle incoming TCP data while simultaneously handling incoming UDP data, rather than switching from a mode where it handles only TCP to a mode where it handles only UDP (and ignoring any data that doesn't correspond to its current mode; because usually ignoring incoming data makes for a bad experience for the client/robot whose requests you are ignoring). This would also allow you to accept() incoming TCP connections at any time (since an incoming TCP connection would cause your TCP_Server socket to select as ready-for-read, at which point you could then call accept() on it again).

Create multiple listening sockets

I'm using winsocks and I am coding an IDS/Honeypot, this is just a small section of it, because at the moment I want the server to listen on multiple sockets (7) and accept the connections, but I've tried to dynamically create the sockets with an array (and the listener etc) but I am still having trouble - I've tried it multiple ways but so far, all I've managed to do is get it working successfully on ONE socket, and LISTEN to all sockets, but not accept them.
So, this was my last attempt but not sure, maybe I need to use threads or declare the sockets differently?
So far, in this small test code, I want:
Initialize server
listen on all 7 ports (1111,2222 ...etc)
Accept an incoming connection on ANY of them
display both messages on client/server
drop the connection
and continue
It's a little sloppy I know, but here is the code so far and I think you can see where I am going with it:
#include <iostream>
#include <winsock2.h>
#include <string>
#pragma comment(lib, "ws2_32.lib")
int main()
{
std::cout<<"Honeypot server [test #1] by Dreamwalker"<<std::endl;
WSADATA wsa;
SOCKET s[7] , new_socket[7];
struct sockaddr_in server , client;
int c, port[7] = {1111,2222,3333,4444,5555,6666,7777};
char *message;
std::cout<<"\nInitialising Winsock and other components...";
if (WSAStartup(MAKEWORD(2,2),&wsa) != 0)
{
std::cout<<"Failed. Error Code :"<<WSAGetLastError()<<std::endl;
return 1;
}
//!IMPORTANT: create multiple new sockets on different ports
int i = 0;
for( i = 0; i < 7; i++)
{
//Create socket
if((s[i] = socket(AF_INET , SOCK_STREAM , 0 )) == INVALID_SOCKET)
{
std::cout<<"Could not create socket : "<< WSAGetLastError()<<std::endl;
}
//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons( port[i] );
//Bind
if( bind(s[i] ,(struct sockaddr *)&server , sizeof(server)) == SOCKET_ERROR)
{
std::cout<<"Bind failed with error code : "<< WSAGetLastError()<<std::endl;
}
/*!ALL CREATION CHECKING DONE, now create multiple sockets on the server
and listen for connections*/
c = sizeof(struct sockaddr_in);
listen(s[i] , SOMAXCONN);
}
///ALL INITIALIZED
std::cout<<"DONE!"<<std::endl;
//Listen/accept incoming connections
std::cout<<"Now listening for connections"<<std::endl;
new_socket[i] = accept(s[i] , (struct sockaddr *)&client, &c);
if (new_socket[i] == INVALID_SOCKET)
{
std::cout<<"accept failed with error code : "<< WSAGetLastError()<<std::endl;
}
//Accepted connection
else{
std::cout<<"Someone has connected to this machine!"<<std::endl;
message = "Hello Client , I have received your connection.\n";
send(new_socket[i] , message , strlen(message) , 0);
closesocket(s[i]);
}
std::cout<<"FINISHED"<<std::endl;
WSACleanup();
getchar();
return 0;
}
And now it's throwing a runtime error as well:
WSAENOTSOCK
10038
Socket operation on nonsocket.
An operation was attempted on something that is not a socket. Either the socket handle parameter did not reference a valid socket,
or for select, a member of an fd_set was not valid.
Which (including debugging) indicates that the socket isn't declared properly when creating on an array, advice?
You code to create/bind/listen is all good. Then:
new_socket[i] = accept(s[i] , (struct sockaddr *)&client, &c);
Firstly, by the time this runs you're outside the loop, and i is 7 which is past the end of the array of sockets, which is why you get the not-a-socket error.
Secondly, accept() is a blocking call, so you can't just call accept() on all the sockets from the same thread the way you did for listen. You need to either have a separate thread block in accept() for each of the ports, or find out which one has a client connection attempt in progress using e.g. select (or epoll - does Windows have that?), then accept() a client on that specific socket (but then you've still got to either create a thread to handle the client read/recvs and write/sends or use select/epoll to find out when there's input ready to read, or more space in output buffers for transmission). There's also a race condition to be wary of if you use select/epoll - a listening socket might signal readiness for accepting a client connection, but by the time you call accept() that connection attempt's failed and forgotten, then if the listening socket hasn't been set to non-blocking mode it'll hang there waiting for another client to connect to that specific socket. IMHO, this is a case where threading is actually easier.
I think it's more "Windowsy" to use IO Completion Ports (you might want to Google), but AFAIK they're totally unportable. Winsock's not an exact match for BSD sockets, but the porting or dual-support effort's small.

Socket send recv functions

I have created a socket using the following lines of code.
Now i change the value of the socket i get like this
m_Socket++;
Even now the send recv socket functions succeeds without throwing SOCKET_ERROR.
I expect that it must throw error.
Am i doing something wrong.
struct sockaddr_in ServerSock; // Socket address structure to bind the Port Number to listen to
char *localIP ;
SOCKET SocServer;
//To Set up the sockaddr structure
ServerSock.sin_family = AF_INET;
ServerSock.sin_addr.s_addr = INADDR_ANY;
ServerSock.sin_port = htons(pLantronics->m_wRIPortNo);
// To Create a socket for listening on wPortNumber
if(( SocServer = socket( AF_INET, SOCK_STREAM, 0 )) == INVALID_SOCKET )
{
return FALSE;
}
//To bind the socket with wPortNumber
if(bind(SocServer,(sockaddr*)&ServerSock,sizeof(ServerSock))!=0)
{
return FALSE;
}
// To Listen for the connection on wPortNumber
if(listen(SocServer,SOMAXCONN)!=0)
{
return FALSE;
}
// Structure to get the IP Address of the connecting Entity
sockaddr_in insock;
int insocklen=sizeof(insock);
//To accept the Incoming connection on the wPortNumber
pLantronics->m_Socket=accept(SocServer,(struct sockaddr*)&insock,&insocklen);
if(pLantronics->m_Socket == INVALID_SOCKET)
{
shutdown(SocServer, 2 );
closesocket(SocServer );
return FALSE;
}
// To make socket non-blocking
DWORD dwNonBlocking = 1;
if(ioctlsocket( pLantronics->m_Socket, FIONBIO, &dwNonBlocking ))
{
shutdown(pLantronics->m_Socket, 2);
closesocket(pLantronics->m_Socket);
return FALSE;
}
pLantronics->m_sModemName = inet_ntoa(insock.sin_addr);
Now i do
m_Socket++;//change to some other number ideally expecting send recv to fail.
Even now the send recv socket functions succeeds without throwing SOCKET_ERROR.
I expect that it must throw error.
Am i doing something wrong.
It's because of the peculiar nature of Windows handles -- when created they are divisible by four and when used their two lowest bits are ignored. Incrementing a handle by one will make m_Socket refer to the same socket as before (only when you increment by four will the function return an error -- unless there is another handle with that value open).
You should not probe for open handles in this manner. While there are other ways to enumerate open handles, you shouldn't use them. Do not depend on the system to keep track of your handles -- track them yourself.

Same socket getting created

I have this piece of code where a server socket is created and is set to listen on a particular port number say 5005. Now once the accept socket function returns the socket that gets created is copied into the m_Socket variable and finally i shutdown the server socket named SocServer which was created locally.
Now my question
Is it possible that the SocServer(created initially) and m_Socket(copied when accept returns) get the same number say 1500.
struct sockaddr_in ServerSock; // Socket address structure to bind the Port Number to listen to
char *localIP ;
SOCKET SocServer;
//To Set up the sockaddr structure
ServerSock.sin_family = AF_INET;
ServerSock.sin_addr.s_addr = INADDR_ANY
ServerSock.sin_port = htons(PortNumber);//port number of 5005
// To Create a socket for listening on PortNumber
if(( SocServer = socket( AF_INET, SOCK_STREAM, 0 )) == INVALID_SOCKET )
{
return FALSE;
}
//To bind the socket with wPortNumber
if(bind(SocServer,(sockaddr*)&ServerSock,sizeof(ServerSock))!=0)
{
return FALSE;
}
// To Listen for the connection on wPortNumber
if(listen(SocServer,SOMAXCONN)!=0)
{
return FALSE;
}
// Structure to get the IP Address of the connecting Entity
sockaddr_in insock;
int insocklen=sizeof(insock);
//To accept the Incoming connection on the wPortNumber
m_Socket=accept(SocServer,(struct sockaddr*)&insock,&insocklen);
//delete the server socket
if(SocServer != INVALID_SOCKET)
{
//To close and shutdown the Socserver
shutdown(SocServer, 2 );
closesocket(SocServer);
}
is it possible that Socserver and m_socket are the same because
as per my code the socket connection is established and for some other reason it gets closed and in TCPView it shows established for a while and then no connection at all.
Note: This happens only in some machines and is not reproducible always. Can any other network related issue be the cause.
Are you certain that the client who is connecting to your server did not close the connection? Also, you did not provide any function which uses the m_Socket so i cannot tell you if there is any problem while handling the incoming connection. I do not think that m_socket and SocServer may end up the same.
In this code:
m_Socket=accept(SocServer,(struct sockaddr*)&insock,&insocklen);
if(SocServer != INVALID_SOCKET)
why do you call accept() with what may apparently be a bad socket? And do you test the value you get back from accept() anywhere?