Reputation: 1498
I'm learning Unix Network Programming Volume 1, I want to reproduce the accept error for RST in Linux.
socket()
, bind()
, listen()
, and sleep(10)
socket()
, connect()
, setsockopt()
of LINGER
, close()
and return
accept()
I think that the 3rd steps will get an error like ECONNABORTED
, but not.
Do I want to know why?
I will appreciate it if you help me.
The follow is server code
:
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <stdio.h>
#include <strings.h>
#include <unistd.h>
int main(int argc, char* argv[]) {
int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
struct sockaddr_in addr;
bzero(&addr, sizeof addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(6666);
inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr);
bind(sock, (struct sockaddr*)(&addr), (socklen_t)(sizeof addr));
listen(sock, 5);
sleep(10);
if (accept(sock, NULL, NULL) < 0)
perror("error");
else
printf("right");
return 0;
}
The following is the client code
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <stdio.h>
#include <strings.h>
#include <unistd.h>
int main(int argc, char* argv[]) {
int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
struct sockaddr_in addr;
bzero(&addr, sizeof addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(6666);
inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr);
connect(sock, (struct sockaddr*)(&addr), (socklen_t)(sizeof addr));
struct linger ling;
ling.l_onoff = 1;
ling.l_linger = 0;
setsockopt(sock, SOL_SOCKET, SO_LINGER, &ling, sizeof ling);
close(sock);
return 0;
}
Upvotes: 1
Views: 581
Reputation: 1498
Linux accept() (and accept4()) passes already-pending network errors on the new socket as an error code from accept(). This behavior differs from other BSD socket implementations. For reliable operation the application should detect the network errors defined for the protocol after accept() and treat them like EAGAIN by retrying. In the case of TCP/IP, these are ENETDOWN, EPROTO, ENOPROTOOPT, EHOSTDOWN, ENONET, EHOSTUNREACH, EOPNOTSUPP, and ENETUNREACH.
http://man7.org/linux/man-pages/man2/accept.2.html
Upvotes: 1
Reputation: 12635
Nope. I think you'll get an empty, but complete connection (with no data). The kernel will manage the complete connection establishment and then it'll get an immediate FIN packet (meaning EOF, not reset) and will handle it (or wait for user space process to close its side, to send the FIN to the other side) For a connection abort you need to reboot the client machine (or the server) without allowing it to send the FIN packets (or disconnecting it from the network before rebooting it) An ACK is never answered, so you won't get a RST sent from an ACK.
RST packets are sent automatically by the kernel when some state mismatch is in between two parties. For this to happen in a correct implementation you must force such a state mismatch (this is why the machine reboot is necessary)
Other ways of getting a RST segment involve bad implementations of TCP, or mangling the packets in transit (changing the sender or receiver sequence numbers in transit)
The purpose of RST packets is not to add functionality to TCP, but to detect misbehaviours, to there should be no means to get a reset with proper use of sockets. Listen syscall is there to allow you to reserve resources in kernel space to allow the user space process to prepare to handle the connection while the clients are trying to connect. If you do what you intend you'll get a connection with no data, but valid connection, SO_LINGER
is there to force a loss of status when machines don't have the time to send the packets to each other... but being connected, the whole connection is handled in the kernel and no abort is to be expected.
Upvotes: 1