Documentation for socket errors - c++

I am creating a server-client application,this issue is that in the code below, I would get a failed to bind or failed to open socket message (see example code below).
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0){
qDebug() << "ERROR netserver: opening socket";
//more code here
}
or
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0){
qDebug() << "ERROR netserver: binding to socket";
//more code here
}
I am aware of C++ devs using the getLastError() but I do not find anything of the sort for sockets.
Does anyone know of a page/tutorial/wiki?

The failed to bind/open socket have typically a (non-developer) system error reason. These are not always that well reported :(
The reasons why that might happen, could be that the socket is already being listened on (ie. you are trying to run a second instance of the same program) or the previous socket haven't been closed properly by the OS after the previous program/instance exited. There are different ways to solve the last issue, but rather check it's not the first issue ;)
The other reason you might get these type of errors, is that the port being requested, is a privileged port, ie. anything less than 1024, which would require root (on Unix) type privilege.
On Unix, the friend there is "netstat -an" (Window I recall have a similar command)

Related

socket() and sendto() dont return error codes when theres no internet connection

Why does socket() not return INVALID_SOCKET when I have no internet connection? I thought it would fail and then I could exit my function. My function's error checking continues till recvfrom() and then just hangs when I have no internet connection. I thought that socket() or sendto() would return an error code when I have no internet connection but they are not. I am trying to rely on their failure as a sign the user has no internet connection and exit my function but thats just not working for some weird reason.
void myFunc()
{
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
struct sockaddr_in server_addr;
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr("myipaddress");
server_addr.sin_port = htons(123);
// Doesn't fail when there's no internet connection
protoent *proto = getprotobyname("udp");
int s = socket(PF_INET, SOCK_DGRAM, proto->p_proto);
if (s == INVALID_SOCKET) {
goto Cleanup;
}
// Doesn't fail when there's no internet connection
char msg[48] = { 0x08, 0, 0, 0, 0, 0, 0, 0, 0 };
int iResult = sendto(s, msg, sizeof(msg), 0, (struct sockaddr *) &server_addr, sizeof(server_addr));
if (iResult == SOCKET_ERROR) {
goto Cleanup;
}
// Hangs when there's no internet connection
memset(msg, 0, sizeof(msg));
struct sockaddr saddr;
socklen_t saddr_l = sizeof(saddr);
iResult = recvfrom(s, msg, 48, 0, &saddr, &saddr_l);
if (iResult == SOCKET_ERROR) {
goto Cleanup;
}
Cleanup:
closesocket(s);
WSACleanup();
}
Because there is no requirement for sockets to be connected to the internet. Many applications use sockets for inter-process communication on a single machine. Such applications can still run fine when there is no internet connection.
sendto() could arguably return an error code; it can (under certain situations, as demonstrated by the desktop notification about network connection status) know that the packet can never be delivered. However, UDP communication and sendto() make no guarantees about delivery whatsoever, and apparently the implementation you are using does not consider the lack of connection worthy of an error code. Arguably this is a quality of implementation issue.
recvfrom() simply waits as long as you have specified (possibly indefinitely) for a message, but never receives one. Again, this is within spec, and again it could be considered a quality of implementation issue whether or not this particular situation is flagged or not.
I looked into the linux man page for sendto (assuming that all relevant the implementations are sufficiently similar to the berkley sockets baseline) here:
http://linux.die.net/man/2/sendto
The documentation does not mention reporting and error if the network stack 'knows' that the message is undeliverable. This is reasonable, since the socket's transport may well not be IP4 or IP6. It could be any transport we chose to write a driver for: packet radio, serial cables or carrier-pigeons (if we could figure out the hardware for loading the printed messages into their satchels).
The only reference to possible errors from the transport is here:
These are some standard errors generated by the socket layer. Additional errors may be generated and returned from the underlying protocol modules; see their respective manual pages.
As mentioned by others, UDP is an unreliable datagram protocol. Unreliability is expected. Non-delivery of a message is expected. Therefore not really an error. There would be little incentive for a protocol-layer author to code for handling transport errors - since they too are expected and not an error in the context of this protocol.
When a socket is opened over TCP, then lack of socket continuity is an error. If the transport reports that packet delivery is not possible (for a sufficiently long time) then this is an error condition in the protocol.

connect to external IP fails

I have been stuck with this problem for ages...
So I coded a game with multiplayer using the BSD sockets/Winsock 2 TCP. My server is up and working, I can connect to it locally (indirectly by filling in my own external ip). Everything seems to be fine. I tested with canyouseeme.org whether my ip and server port were properly port forwarded, and it was perfectly working. Then I sent my client to a friend to test it out by connecting to the server, and it failed all the time. I expected him to have connected, but I could not see anything on the server side (while canyouseenme.org even popped up as invalid client). I do not get it, do I have to do something special for external connecting in TCP?
Here is my connect function:
int CConnectSocket(CSocket s, unsigned short port, char* ipaddress)
{
SOCKADDR_IN target;
target.sin_family = AF_INET;
target.sin_port = htons(port);
target.sin_addr.s_addr = htonl(inet_addr(ipaddress));
if (connect(s, (SOCKADDR*)&target, sizeof(target)) == SOCKET_ERROR)
{
if (WSAGetLastError() == WSAEISCONN)
return CTCP_DONE;
else if (WSAGetLastError() != WSAEWOULDBLOCK && WSAGetLastError() != WSAEALREADY)
{
strcpy(inerr, "CConnectSocket: Failed to connect the socket. Error ");
char f[6];
sprintf(f, "%d", WSAGetLastError());
strcat(inerr, f);
return CTCP_ERROR;
}
return CTCP_WAIT;
}
return CTCP_DONE;
}
I keep looping this function until CTCP_DONE is returned (meaning I connected). My friend reported he timed out (so it returned CTCP_WAIT for too long). Again, I'm sure the client is the fault because my server was able to accept an external connection from canyouseeme.org. The IP address and port I fill in work because I can connect locally. If I change the port, local connection doesn't work anymore (proof that it is a correct argument). Changing the IP does yield the same result.
I appreciate any help! Hopefully I can solve this problem and begin the multiplayer.
EDIT
void CEngine::CSetSockAddr(CSockAddr* address, unsigned short port, char* ipaddress)
{
memset(address, 0, sizeof(CSockAddr));
address->sin_family = AF_INET;
address->sin_port = htons(port);
address->sin_addr.s_addr = htonl(inet_addr(ipaddress));
}
This is my socket address function. When I remove the htonl function, it works at my friend's side, but no at my side any more (I also host the server). My friend BTW uses XP, but since I called to use 2.2 WinSock that should be no issue. At least I hope that the setup function for WinSock guarantees a 2.2 implementation if it returns true.
EDIT 2
Hello guys,
I have got everything up and working now. It seems that if I add htonl I can connect as the host with the external IP rather than connecting with the loopback 127.0.0.0.1 or sth like that. So now I would like to know, how do I detect whether I am connecting to a server that I host? That would be a nice trick. Happy new year all!
Is very difficult to help you without a console... but you can talk with your friend and try this:
From your friend's PC, make a ping against your server.
If you recieve an answer, use tracert or traceroute to find out what's the problem
What's the route model of your friend? probably it has a System Event Log where you can check for rejected connections.
Luck!
You need to remove the htonl() call when calling inet_addr(). connect() expects the IP to be in network byte order, and inet_addr() returns the IP in network byte order, so there is no need to swap the bytes, on any platform.
Try this:
int CConnectSocket(CSocket s, unsigned short port, char* ipaddress)
{
SOCKADDR_IN target = {0};
target.sin_family = AF_INET;
target.sin_port = htons(port);
target.sin_addr.s_addr = inet_addr(ipaddress);
if (connect(s, (SOCKADDR*)&target, sizeof(target)) == SOCKET_ERROR)
{
int err = WSAGetLastError();
switch (err)
{
case WSAEISCONN:
return CTCP_DONE;
case WSAEWOULDBLOCK:
case WSAEALREADY:
return CTCP_WAIT;
default:
sprintf(inerr, "CConnectSocket: Failed to connect the socket. Error %d", err);
return CTCP_ERROR;
}
}
return CTCP_DONE;
}

How to deal with short reads with Winsock2?

I'm having trouble with receiving data over a network using Winsock2, with Windows. I'm trying to use a simple client and server system to implement a file transfer program. With our current code, the last packet coming in doesn't get appended to the file because it's not the size of the buffer. So, the file transfer doesn't quite completely, throws an error, and breaks. It's not always the very last packet, sometimes it's earlier.
Here is a snippet of the Server code:
int iResult;
ifstream sendFile(path, ifstream::binary);
char* buf;
if (sendFile.is_open()) {
printf("File Opened!\n");
// Sends the file
while (sendFile.good()) {
buf = new char[1024];
sendFile.read(buf, 1024);
iResult = send(AcceptSocket, buf, (int)strlen(buf)-4, 0 );
if (iResult == SOCKET_ERROR) {
wprintf(L"send failed with error: %d\n", WSAGetLastError());
closesocket(AcceptSocket);
WSACleanup();
return 1;
}
//printf("Bytes Sent: %d\n", iResult);
}
sendFile.close();
}
And here is a snippet of the Client code:
int iResult;
int recvbuflen = DEFAULT_BUFLEN;
char recvbuf[DEFAULT_BUFLEN] = "";
do {
iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
if ( iResult > 0){
printf("%s",recvbuf);
myfile.write(recvbuf, iResult);
}
else if ( iResult == 0 ) {
wprintf(L"Connection closed\n");
} else {
wprintf(L"recv failed with error: %d\n", WSAGetLastError());
}
} while( iResult > 0 );
myfile.close();
When trying to transfer a file that is a dictionary, it can break at random times. For example, one run broke early in the S's and appended weird characters to the end, which isn't rare:
...
sayable
sayer
sayers
sayest
sayid
sayids
saying
sayings
╠╠╠╠╠╠╠╠recv failed with error: 10054
What can I do to handle these errors and weird characters?
The error is happening on the server side. You're getting a "Connection reset by peer" error.
This line - buf = new char[1024]; - is clearly problematic and is likely causing the server to crash because it runs out of memory. There is no clean up happening. Start by adding the appropriate delete statement, probably best placed after the send call. If that doesn't fix it I would use a small test file and step through that while loop in the server code.
P.S. A better solution than using new and delete in your loop is to reuse the existing buff. The compiler might optimize this mistake out but if it doesn't you're severely hindering the applications performance. I think you actually should just move buf = new char[1024]; outside of the loop. buf is a char pointer so read will continue to overwrite the contents of buf if you pass it buf. Re allocating the buffer over and over is not good.
With regard to the error MSDN says:
An existing connection was forcibly closed by the remote host. This normally results if the peer application on the remote host is suddenly stopped, the host is rebooted, the host or remote network interface is disabled, or the remote host uses a hard close (see setsockopt for more information on the SO_LINGER option on the remote socket). This error may also result if a connection was broken due to keep-alive activity detecting a failure while one or more operations are in progress. Operations that were in progress fail with WSAENETRESET. Subsequent operations fail with WSAECONNRESET.
First, using the new operator in a loop might not be good, especially without a corresponding delete. I'm not a C++ expert, though (only C) but I think it is worth checking.
Second, socket error 10054 is "connection reset by peer" which tells me that the server is not performing what is called a graceful close on the socket. With a graceful close, WinSock will wait until all pending data has been received by the other side before sending the FIN message that breaks the connection. It is likely that your server is is just closing immediately after the final buffer is given to WinSock without any time for it to get transmitted. You'll want to look into the SO_LINGER socket options -- they explain the graceful vs non-graceful closes.
Simply put, you either need to add your own protocol to the connection so that the client can acknowledge receipt of the final data block, or the server side needs to call setsocketopt() to set a SO_LINGER timeout so that WinSock will wait for the TCP/IP acknowledgement from the client side for the final block of data before issuing the socket close across the network. If you don't do at least ONE of those things, then this problem will occur.
There's also another article about that here that you might want to look at:
socket error 10054
Good luck!

Socket Exception: "There are no more endpoints available from the endpoint mapper"

I am using winsock and C++ to set up a server application. The problem I'm having is that the call to listen results in a first chance exception. I guess normally these can be ignored (?) but I've found others having the same issue I am where it causes the application to hang every once in a while. Any help would be greatly appreciated.
The first chance exception is:
First-chance exception at 0x*12345678* in MyApp.exe: 0x000006D9: There are no more endpoints available from the endpoint mapper.
I've found some evidence that this could be cause by the socket And the code that I'm working with is as follows. The exception occurs on the call to listen in the fifth line from the bottom.
m_accept_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (m_accept_fd == INVALID_SOCKET)
{
return false;
}
int optval = 1;
if (setsockopt (m_accept_fd, SOL_SOCKET, SO_REUSEADDR,
(char*)&optval, sizeof(optval)))
{
closesocket(m_accept_fd);
m_accept_fd = INVALID_SOCKET;
return false;
}
struct sockaddr_in local_addr;
local_addr.sin_family = AF_INET;
local_addr.sin_addr.s_addr = INADDR_ANY;
local_addr.sin_port = htons(m_port);
if (bind(m_accept_fd, (struct sockaddr *)&local_addr,
sizeof(struct sockaddr_in)) == SOCKET_ERROR)
{
closesocket(m_accept_fd);
return false;
}
if (listen (m_accept_fd, 5) == SOCKET_ERROR)
{
closesocket(m_accept_fd);
return false;
}
On a very busy server, you may be running out of Sockets. You may have to adjust some TCPIP parameters. Adjust these two in the registry:
HKLM\System\CurrentControlSet\Services\Tcpip\Parameters
MaxUserPort REG_DWORD 65534 (decimal)
TcpTimedWaitDelay REG_DWORD 60 (decimal)
By default, there's a few minutes delay between releasing a network port (socket) and when it can be reused. Also, depending on the OS version, there's only a few thousand in the range that windows will use. On the server, run this at a command prompt:
netstat -an
and look at the results (pipe to a file is easiest: netstat -an > netstat.txt). If you see a large number of ports from 1025->5000 in Timed Wait Delay status, then this is your problem and it's solved by adjusting up the max user port from 5000 to 65534 using the registry entry above. You can also adjust the delay by using the registry entry above to recycle the ports more quickly.
If this is not the problem, then the problem is likely the number of pending connections that you have set in your Listen() method.
The original problem has nothing to do with winsock. All the answers above are WRONG. Ignore the first-chance exception, it is not a problem with your application, just some internal error handling.
Are you actually seeing a problem, e.g., does the program end because of an unhandled exception?
The debugger may print the message even when there isn't a problem, for example, see here.
Uhh, maybe it's because you're limiting greatly the maximum number of incoming connections?
listen (m_accept_fd, 5)
// Limit here ^^^
If you allow a greater backlog, you should be able to handle your problem. Use something like SOMAXCONN instead of 5.
Also, if your problem is only on server startup, you might want to turn off LINGER (SO_LINGER) to prevent connections from hanging around and blocking the socket...
This won't answer your question directly, but since you're using C++, I would recommend using something like Boost::Asio to handle your socket code. This gives you a nice abstraction over the winsock API, and should allow you to more easily diagnose error conditions.

socket programming in client

I wrote this program in C++ and on Linux platform.
I wrote a client and server socket program.
In that client program, I wrote socket function and immediately after that I am doing some other actions not at all depending on socket (I wrote 2 for loops for some other logic).
After that I prepared the structures required for the socket and I wrote the connect function...in that I am getting error as unable to connect because connect is returning -1..
But for the same program, if I write that for loop's logic above the socket function and immediately after that structures, and connect function, then it is working fine..
What might be the reason I am not able to get? Please help me in this aspect. Here is my code
here index1 and index 2 are simple integer variables..The configstring is a char array contains 127.0.0.1:7005(address and port number)...address and port are char array variables to store address and port number..
struct sockaddr_in s1;
for(index1=0;configstring[index1]!=':';index1++)
{
address[index1] = configstring[index1];
}
address[index1++]='\0';
for(index2=0;configstring[index1]!='\0';index1++,index2++)
{
port[index2] = configstring[index1];
}
port[index2++]='\0';
int port_num = changeto_int(port);
if((sock_fd = socket(AF_INET,SOCK_STREAM,0)) == -1)
{
printf("unable to create a socket\n");
return 0;
}
s1.sin_family=AF_INET;
s1.sin_port=htons(port_num);
s1.sin_addr.s_addr=inet_addr(address);
memset(s1.sin_zero, '\0', sizeof s1.sin_zero);
int errno;
if(connect(sock_fd,(struct sockaddr *)&s1,sizeof(s1)) == -1)
{
printf("error:unable to connect\n");
printf("Error in connect(): %s\n", strerror( errno));
return -1;
}
First, never do something like this:
int errno;
errno is already defined for you.
More than that I suggest you to use perror() instead of
printf("Error in connect(): %s\n", strerror( errno));
Third, you can't call printf and than strerror( errno) because printf whould change
value of errno to success.
Third, I'd sugget to take a look on examples in internet and start from them.
I'd suggest to read man select_tut there are many good written code examples
of how to do and what.
Have you tried calling strerror on errno? connect() returning -1 would mean that errno has been set and should have more information about your error.
printf("Error in connect(): %s\n", strerror(errno));
Have you considered simply that your receiver is not listening properly for connections?
As others said, use perror to check errno and print some usable debug to the console.
Without your sample code there is no way to help you. There could be a million reasons. Perhaps there's a firewall on your machine blocking connections? Perhaps the server isn't listening, or is on an incorrect port (you did convert to network byte order didn't you?). Perhaps the client is connecting to a wrong address or port. Maybe you haven't set up your structures correctly.
I recommend reading Beej's Socket Programming Doo-Daa for a good introduction to sockets on Unix (and it follows on to Windows).
struct sockaddr_in s1;
could you please try memset of s1, at the beginning of your program.
I have experienced some thing similar to this.
Could you print debugging info about the address and port string ?
Remove the errno thing, include and use perror.
Compile with -Wall
Judging from your comment that perror() returns "socket operation on non socket"... How are your address and port variables declared? Is it possible that port[index2++]='\0' somehow overwrite onto sock_fd or such?
try adding :
inet_pton(AF_INET, your IP address, (void *)&server_address);
before making connection to the server.
Also,I have a hunch that the problem behind the scene could be around serverside.
Low level socket programming is tedious and error prone. You would be well advised to start using frameworks like Boost or ACE that shield you from these low level details and allow you to program platform independent.