Linux sockets: Difference between revisions

From miki
Jump to navigation Jump to search
Line 66: Line 66:


For more information, see [http://man7.org/linux/man-pages/man7/socket.7.html socket(7)] and [http://man7.org/linux/man-pages/man7/ip.7.html ip(7)] manpages.
For more information, see [http://man7.org/linux/man-pages/man7/socket.7.html socket(7)] and [http://man7.org/linux/man-pages/man7/ip.7.html ip(7)] manpages.

=== Program crashes on <code>write</code> with exit code -13 ===
Exit code -13 means the program died because of SIGPIPE signal, meaning it tried to write to a closed socket.

Solutions:
* Ignore SIGPIPE in the program [https://stackoverflow.com/questions/16124019/writesocket-buff-length-makes-crash]:
<source lang="c">
signal (SIGPIPE, SIG_IGN);
</source>
* Use <code>send</code> instead of <code>write</code>. Send returns -1 and set <code>errno</code> to <code>EPIPE</code> rather than generating a fatal SIGPIPE like <code>write</code> does [https://stackoverflow.com/questions/15793928/c-linux-tcp-ip-program-crashes-when-calling-write]:
<source lang="c">
n = send(newsockfd, data.c_str(), data.length()+1, MSG_NOSIGNAL);
</source>

Revision as of 05:10, 28 September 2018

Tutorials

A thoough step-by-step example of client and socket code.
Simple example of client and server code using Linux sockets.

References

A very detailed answer about the differences between SO_REUSEADDR and SO_REUSEPORT.
A course on internet technologies, including Domain Naming (DNS...), the IP protocol, the TCP protocol, ...
  • Manpages:

Troubleshooting

Use errno / perror / strerror to get error

if( bind(socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0)
{
    printf("bind failed: %s (errno %d)", strerror(errno), errno);
    return 1;
}

Or there is also the perror function:

if( bind(socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0)
{
    perror("bind failed");
    return 1;
}

Use netstat to get socket status

./server
# bind done
# Waiting for incoming connections...
# Connection accepted
# Handler assigned
# ^C

./server
# bind failed: Address already in use (errno 98)

netstat -a | grep 8888
# tcp        0      0 zavcxl0005:58888        165.225.76.32:http      ESTABLISHED
# tcp        0      0 zavcxl0005:48888        10.75.126.1:https       ESTABLISHED
# tcp        0      0 localhost.localdom:8888 localhost.localdo:50310 TIME_WAIT  

# ... So port is still in use

bind failed: Address already in use (errno 98)

Call to bind fails with error

bind failed: Address already in use (errno 98)

On a server, this is probably due to an old instance of the server that tries to bind to the same port and address [1].

As a fix, try to bind with option SO_REUSEADDR and/or SO_REUSEPORT. From SO:

if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &(int){ 1 }, sizeof(int)) < 0)
    error("setsockopt(SO_REUSEADDR) failed");


For more information, see socket(7) and ip(7) manpages.

Program crashes on write with exit code -13

Exit code -13 means the program died because of SIGPIPE signal, meaning it tried to write to a closed socket.

Solutions:

  • Ignore SIGPIPE in the program [2]:
signal (SIGPIPE, SIG_IGN);
  • Use send instead of write. Send returns -1 and set errno to EPIPE rather than generating a fatal SIGPIPE like write does [3]:
n = send(newsockfd, data.c_str(), data.length()+1, MSG_NOSIGNAL);