How to make sure a TCP socket connects at creation time - c++

I have a client application that sends TCP packets. Currently, my application does this:
creates a socket, binds and sends the packets.
struct sockaddr_in localaddress;
localaddress.sin_port = htons(0);
localaddress.sin_addr.s_addr = INADDR_ANY;
int socket;
socket = socket(AF_INET, SOCK_STREAM, 0));
bind(socket, (struct sockaddr *)&sin,sizeof(struct sockaddr_in) );
And in another thread, the application connects and sends the packets:
struct socketaddr_in remoteaddress;
// omitted: code to set the remote address/ port etc...
nRet = connect (socket, (struct sockaddr * ) & remoteaddress, sizeof (sockaddr_in ));
if (nRet == -1)
nRet = WSAGetLastError();
if (nRet == WSAEWOULDBLOCK) {
int errorCode = 0;
socklen_t codeLen = sizeof(int);
int retVal = getsockopt(
socket, SOL_SOCKET, SO_ERROR, ( char * ) &errorCode, &codeLen );
if (errorCode == 0 && retVal != 0)
errorCode = errno;
}
/* if the connect succeeds, program calls a callback function to notify the socket is connected, which then calls send() */
Now I want to specify a port range for local port, so I changed the code to
nPortNumber = nPortLow;
localaddress.sin_port = htons(nPortNumber);
and loops nPortNumber in my port range, e.g ( 4000 - 5000 ) until the bind succeeds.
Since I always start my nPortNumber from the low port, if a socket is previously created on the same port, I get the WSAEADDRINUSE error as errorCode, which is too late for me because it has already passed the socket creation stage. (Why didn't I get WSAEADDRINUSE at bind() or connect()?)
Is there a way I can get the WSAEADDRINUSE earlier or is there a way to create a socket in the port range that binds and connects?
Thanks in advance!

I cannot answer with 100% certainty as for that I should know at which point you actually get WSAEADDRINUSE.
IN any case, it is normal you don't get it at bind, because you use INADDR_ANY. IIRC, this actually delays the bind process to the actual connect (my guess is it then changes the INADDR based on routing for the remote addr). However, as far as I know, you should then actually get the error at the call of connect...

Related

C++ Winsock UDP sendto succeeds but I don't see the data being sent

I am working with UDP sockets over an ethernet interface between my workstation (192.168.0.1) and my WinCE6 device (192.168.0.100).
From my workstation I can send UDP packets toward my WinCE device where I have a receiving socket set up and properly receiving data on port 9002; the device then properly echoes back data to my workstation.
I want my device to answer to my workstation on a specific port: 9001.
This is the server running into my device, it is the same as this but I modified the socket bind to the address of the specific interface and I changed the PORT define:
#define BUFLEN 512 //Max length of buffer
#define PORT 9002 //The port on which to listen for incoming data
void test_udp( void )
{
SOCKET s;
struct sockaddr_in server, si_other;
int slen , recv_len;
char buf[BUFLEN];
WSADATA wsa;
slen = sizeof(si_other) ;
//Initialise winsock
if (WSAStartup(MAKEWORD(2,2),&wsa) != 0)
{
return;
}
//Create a socket
if((s = socket(AF_INET , SOCK_DGRAM , 0 )) == INVALID_SOCKET)
{
printf( "Could not create socket : %d" , WSAGetLastError());
}
//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = htonl( 0xC0A80064 );
server.sin_port = htons( PORT );
//Bind
if( bind(s ,(struct sockaddr *)&server , sizeof(server)) == SOCKET_ERROR)
{
return;
}
//keep listening for data
while(1)
{
//clear the buffer by filling null, it might have previously received data
memset(buf,'\0', BUFLEN);
//try to receive some data, this is a blocking call
if ((recv_len = recvfrom(s, buf, BUFLEN, 0, (struct sockaddr *) &si_other, &slen)) == SOCKET_ERROR)
{
return;
}
// *** CHANGE THE SEND PORT
si_other.sin_port = htons( 9001 );
//now reply the client with the same data
if (sendto(s, buf, recv_len, 0, (struct sockaddr*) &si_other, slen) == SOCKET_ERROR)
{
return;
}
}
closesocket(s);
WSACleanup();
return;
}
When I added the line below the // *** CHANGE THE SEND PORT comment to try to send the data back to port 9001, I am getting an appropriate return value for sendto which matches the number of bytes I expect to have been sent, but I don't see the data coming on my workstation (listening on 9001).
I have been banging my head against this and I cant see anything wrong. In the modified example, Any help would be greatly appreciated.
UPDATE: A firewall on my development PC was at fault. It allowed traffic back on the same port my PC was sending on, but blocked traffic on any other port. Resolving that allowed the the traffic to be sent without code changes. I had disabled the firewall previously, but did not realize that the OS had flagged the ethernet as a "public network", which still had the firewall enabled.
If, as you said, you are not getting a SOCKET_ERROR from the sendto and you are seeing an appropriate return value, this means that your OS was able to find a route toward the destination IP and was able to buffer your send request.
To change the send port it's ok if you want to answer to a different port with respect to the one from which you received data but note that this is not a typical case; the si_other struct in fact will contain the source address after the recvfrom and so the source port too. So keep your code as it is on your device side.
If you are not seeing data flowing to your workstation probably, in a simple networking context as your development environment, the problem is on the workstation: it is not receiving data.
I agree with #Daniel that you have to investigate with WireShark to see what's happening to packets.
Hope this helps

C++ Reconnect TCP Server to Client after Client restart

I want to implement a 'flexible' TCP connection where I can randomly shutdown and restart both the Server and the Client. The other one should then automatically detect the shutdown and enter try to reconnect. I successfully implemented this s.t. I can shutdown and restart the server. The client discovers the shutdown (via recv(...) == 0) and then closes the connection (it therefore closes the sockets close(this->sockfd_) and close(this->newsockfd_)).
Unfortunately I am not able to get this working the other way around. I initialize the server (using the class constructor) the following way:
tcpServer::tcpServer(int _port) {
this->sockfd_ = -1;
this->port_ = _port;
this->connected_ = false;
if ((this->sockfd_ = socket(AF_INET, SOCK_STREAM, 0)) < 0)
this->dieWithError("ERROR opening Socket");
else
printf("-> Port %d: Socket opened\n", this->port_);
// get rid of "address already in use" error message
int yes = 1;
setsockopt(this->sockfd_, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
/* assign values to the fields of struct sockaddr_in */
bzero((char *) &this->serv_addr_, sizeof(this->serv_addr_));
this->serv_addr_.sin_family = AF_INET;
this->serv_addr_.sin_port = htons(this->port_);
this->serv_addr_.sin_addr.s_addr = INADDR_ANY;
/* bind the socket to an address */
if (bind(this->sockfd_, (struct sockaddr *) &this->serv_addr_, sizeof(this->serv_addr_)) < 0) {
printf("-> Port %d:", this->port_);
this->dieWithError("ERROR on binding");
}
printf("-> Binding successful. Start TCP client in new terminal\n");
fflush(stdout);
/* listen for connections and accept a connection */
listen(this->sockfd_, 5);
this->clilen_ = sizeof(this->cli_addr_);
if ((this->newsockfd_ = accept(this->sockfd_, (struct sockaddr *) &this->cli_addr_, &this->clilen_)) < 0)
this->dieWithError("Error on accept");
else {
printf("-> Connection established\n");
this->connected_ = true;
}
}
So once the server detects that the connection is closed, it enters a loop where it tries to reconnect using the following code:
void tcpServer::connect() {
if (this->sockfd_ == -1) {
/* create socket */
if ((this->sockfd_ = socket(AF_INET, SOCK_STREAM, 0)) < 0)
this->dieWithError("ERROR opening Socket");
else
printf("-> Port %d: Socket opened\n", this->port_);
// get rid of "address already in use" error message
int reuse_address = 1;
setsockopt(this->sockfd_, SOL_SOCKET, SO_REUSEADDR, &reuse_address, sizeof(int));
/* listen for connections and accept a connection */
listen(this->sockfd_, 5);
this->clilen_ = sizeof(this->cli_addr_);
if ((this->newsockfd_ = accept(this->sockfd_, (struct sockaddr *) &this->cli_addr_, &this->clilen_)) < 0)
this->dieWithError("Error on accept");
else {
printf("-> Connection established\n");
this->connected_ = true;
}
}
}
Some simple debugging output tells me that in the reconnect-mode, the server gets stuck in the
accept(this->sockfd_, (struct sockaddr *) &this->cli_addr_, &this->clilen_) call. Another observation I made is that the client does not shut down properly (via ctrl-c), i.e., it gets stuck in a loop somewhere and does not properly close the connection.
Since I am a total beginner with the TCP stuff, I would be very happy if someone could point me to the right direction. Thank you.

Server socket finishes when client closes connection

I'm trying to create a server socket with C++ in order to accept one client connection at a time. The program successfully creates the server socket and waits for incoming connections but when a connection is closed by the client the program would loop endlessly. Otherwise if the connection is interrupted it would keep waiting for new connections as expected. Any idea why this is happening? Thanks
This is my C++ server code:
int listenfd, connfd, n;
struct sockaddr_in servaddr, cliaddr;
socklen_t clilen;
pid_t childpid;
char mesg[1000];
listenfd = socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(32000);
bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
listen(listenfd, 1024);
while (true) {
clilen = sizeof(cliaddr);
connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &clilen);
if ((childpid = fork()) == 0) {
close (listenfd);
while (true) {
n = recvfrom(connfd, mesg, 1000, 0, (struct sockaddr *)&cliaddr, &clilen);
sendto(connfd, mesg, n, 0, (struct sockaddr *)&cliaddr, sizeof(cliaddr));
mesg[n] = 0;
printf("%d: %s \n", n, mesg);
if (n <= 0) break;
}
close(connfd);
}
}
For some reason when the client closes the connection the program would keep printing -1: even with the if-break clause..
You never close connfd in parent process (when childpid != 0), and you do not properly terminate child process that will try to loop. Your if block should look like :
if ((childpid = fork()) == 0) {
...
close(connfd);
exit(0);
}
else {
close(connfd);
}
But as you say you want to accept one connection at a time, you can simply not fork.
And as seen in other answers :
do not use mesg[n] without testing n >= 0
recvfrom and sendto are overkill for TCP simply use recv and send (or even read and write)
mesg[n] = 0;
This breaks when n<0, ie. socket closed
The problem is your "n" and recvfrom. You are having a TCP client so the recvfrom won't return the correct value.
try to have a look on :
How to send and receive data socket TCP (C/C++)
Edit 1 :
Take note that you do the binding not connect() http://www.beej.us/guide/bgnet/output/html/multipage/recvman.html
means there is an error in recieving data, errno will be set accordingly, please try to check the error flag.
you've written a TCP server, but you use recvfrom and sendto which are specific for connection-less protocols (UDP).
try with recv and send. maybe that might help.

SQLBrowseConnect doesn't seem to enumerate servers on local domain

I am trying to enumerate local SQL instances using SQLBrowseConnect. Generally speaking, this is working fine, but we have one set up which results in an SQLExpress instance not being discovered. Here is the code in question:
SQLSetConnectAttr(hSQLHdbc,
SQL_COPT_SS_BROWSE_SERVER,
_T("(local)"),
SQL_NTS);
CString inputParam = _T("Driver={SQL Server}");
SQLBrowseConnect(hSQLHdbc,
inputParam,
SQL_NTS,
szConnStrOut,
MAX_RET_LENGTH,
&sConnStrOut);
In the failed instance, the code is running on a domain controller. The missing local instance of SQL is an SQLExpress instance (version 9). However, the puzzling thing is that running sqlcmd -L shows the missing instance without any problems.
Am I missing something really silly? Please remember that on other systems and set ups there is no issue.
After much investigation, I couldn't really find out what the problem was specifically. This one machine just would not discover its own instances of SQL using SQLBrowseConnect. I therefore decided to write my own version. Discovering SQL instances turns out to be pretty easy. You just send a broadcast UDP packet to port 1434 containing the payload 0x02 (1 byte) and wait for SQL servers to respond. They respond with one packet per server which details all the instances on that machine. The code required to do this is shown below:
// to enumerate sql instances we simple send 0x02 as a broadcast to port 1434.
// Any SQL servers will then respond with a packet containing all the information
// about installed instances. In this case we only send to the loopback address
// initialise
WSADATA WsaData;
WSAStartup( MAKEWORD(2,2), &WsaData );
SOCKET udpSocket;
struct sockaddr_in serverAddress;
if ((udpSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
{
return;
}
// set up the address
serverAddress.sin_family = AF_INET;
serverAddress.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
serverAddress.sin_port = htons(1434);
// the payload
char payload = 0x02;
// config the port for broadcast (not totally necessary right now but maybe in the future)
BOOL broadcast = TRUE;
setsockopt(udpSocket, SOL_SOCKET, SO_BROADCAST, reinterpret_cast<const char*>(&broadcast), sizeof(BOOL));
// receive address info
sockaddr_in RecvAddr;
RecvAddr.sin_family = AF_INET;
RecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
sockaddr_in SenderAddr;
int SenderAddrSize = sizeof (SenderAddr);
// bind the socket to the receive address info
int iResult = bind(udpSocket, (SOCKADDR *) & RecvAddr, sizeof (RecvAddr));
if (iResult != 0)
{
int a = WSAGetLastError();
return;
}
if (sendto(udpSocket, &payload, 1, 0, (struct sockaddr *) &serverAddress, sizeof(serverAddress)) < 0)
{
int a = WSAGetLastError();
return;
}
// set up a select so that if we don't get a timely response we just bomb out.
fd_set fds ;
int n ;
struct timeval tv ;
// Set up the file descriptor set.
FD_ZERO(&fds) ;
FD_SET(udpSocket, &fds) ;
// Set up the struct timeval for the timeout.
tv.tv_sec = 5 ;
tv.tv_usec = 0 ;
// Wait until timeout or data received.
n = select ( (int)udpSocket, &fds, NULL, NULL, &tv ) ;
if ( n == 0)
{
// timeout
return;
}
else if( n == -1 )
{
// error
return;
}
// receive buffer
char RecvBuf[1024];
int BufLen = 1024;
memset(RecvBuf, 0, BufLen);
iResult = recvfrom(udpSocket,
RecvBuf,
BufLen,
0,
(SOCKADDR *) & SenderAddr,
&SenderAddrSize);
if (iResult == SOCKET_ERROR)
{
int a = WSAGetLastError();
return;
}
// we have received some data. However we need to parse it to get the info we require
if (iResult > 0)
{
// parse the string as required here. However, note that in my tests, I noticed
// that the first 3 bytes always seem to be junk values and will mess with string
// manipulation functions if not removed. Perhaps this is why SQLBrowseConnect
// was having problems for me???
}

*nix & C++ writing a non-blocking socket server

I'm experiencing some issues with rewriting my blocking socket server to a non-blocking version.
Actually, I can't seem to even get socket connected anymore, I've been googling for the most of today, and trying different solutions I find here and there, but none of them seem to work properly...
Currently my server loop just keeps timeouting the select() call, with no new sockets accepted.
Client socket seems to connect on some level, since if I start it, it will block trying to write, and if I close the server, it will inform that connection was reset by peer.
Is the following a correct assumption?
With non-blocking server I should normally open the socket, then set it's flags to non-blocking, bind it, and the start calling select for read file descriptor and wait for it to populate ?
I need to remove old blocking "accept()" call, which was waiting endlessly..
If I try calling accept, it will -1 on me now...
Here is the relevant code I'm trying now
fd_set incoming_sockets;
....
int listener_socket, newsockfd, portno;
socklen_t clilen;
struct sockaddr_in serv_addr, cli_addr;
....
listener_socket = socket(AF_INET, SOCK_STREAM, 0); //get socket handle
int flags = fcntl(listener_socket, F_GETFL, 0);
if( fcntl(listener_socket, F_SETFL, flags | O_NONBLOCK) < 0 )
log_writer->write_to_error_log("Error setting listening socket to non blocking", false);
memset(&serv_addr, 0, sizeof(struct sockaddr_in));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
....
if (bind(listener_socket, (struct sockaddr *) &serv_addr,
sizeof(struct sockaddr_in)) < 0)
{
log_writer->write_to_error_log("Unable to bind socket, aborting!", true);
}
....
struct timeval timeout;
timeout.tv_sec = 1;
timeout.tv_usec = 0;
int ready_sockets = 0;
listen(listener_socket,1);
FD_ZERO(&incoming_sockets);
FD_SET(listener_socket, &incoming_sockets);
while(true)
{
ready_sockets = select(listener_socket + 1 , &incoming_sockets, (fd_set * ) 0, (fd_set * ) 0, &timeout );
if(ready_sockets == 0)
{
//I loop here now for ever
std::cout << "no new sockets available, snooze 2\n";
sleep(2);
} else
{
std::cout << "connection received!\n";
Since you don't show the whole loop, I don't know if you do it later, but you should initialize the descriptor sets and timeout structure before every call to select.
You should mover the fd_zero() fd_set() macros inside the loop, select will actually change the bitmasks in the fd_sets (and the timeout value). Reinitialise them on every iteration. Also check for select returning -1 and the associated errno (EPIPE ...)
while(true)
{
FD_ZERO(&incoming_sockets);
FD_SET(listener_socket, &incoming_sockets);
ready_sockets = select(listener_socket + 1 , &incoming_sockets, (fd_set * ) 0, (fd_set * ) 0, &timeout );
if(ready_sockets == 0)
{
... }