I've been approaching network programming these days, and I wrote two simple routines to check if I got it right. So I built the server on the desktop and started it, then I built the client on the laptop and I ran it, and everything went as expected. When I tried to run them the second time and on, the server kept looping and the client after two seconds gave "Error connecting!". If I try again after fifteen minutes it works, but then I have to wait again. Where am I wrong? The computers are both connected to my LAN, 79.13.199.165 is the IP of my modem/router, which forwards every incoming connection on port 53124 to the desktop. This problem doesn't occur when running both server and client on the same PC.
server.c
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
int main () {
struct sockaddr_in sa;
sa.sin_family = AF_INET;
sa.sin_port = htons(53124);
sa.sin_addr.s_addr = htonl(INADDR_ANY);
memset(sa.sin_zero, '\0', sizeof(sa.sin_zero));
int mysocket = socket(PF_INET, SOCK_STREAM, 0);
bind(mysocket, (struct sockaddr*)&sa, sizeof(sa));
listen(mysocket, 5);
int inc;
struct sockaddr_in inc_addr;
socklen_t inc_addr_size = sizeof(inc_addr);
inc = accept(mysocket, (struct sockaddr*)&inc_addr, &inc_addr_size);
if (inc != -1) {
printf("accepting client\n");
}
send(inc, "ciao", sizeof("ciao"), 0);
close(inc);
return 0;
}
client.c
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
int main () {
struct sockaddr_in sa;
sa.sin_family = AF_INET;
sa.sin_port = htons(53124);
sa.sin_addr.s_addr = inet_addr("79.13.199.165");
memset(sa.sin_zero, '\0', sizeof(sa.sin_zero));
int mysocket = socket(PF_INET, SOCK_STREAM, 0);
if (mysocket == -1) {
printf("Could not create socket!\n");
}
if (connect(mysocket, (struct sockaddr*)&sa, sizeof(sa)) == -1) {
printf("Error connecting!\n");
}
char message[5];
memset(message, '\0', sizeof(message));
recv(mysocket, message, 5, 0);
printf("%s\n", message);
return 0;
}
When the server closes the socket, a couple of ACK packets get sent backwards and forwards across the connection. There's no way to tell if the last ACK gets delivered successfully, so the connection goes into the TIME_WAIT state for a bit. This basically gives the TCP stack time to wait for any lost packets and throw them away.
It's possible to ignore this and reuse the socket straight away by setting SO_REUSEADDR using setsockopt(). There is a small danger that subsequent connects might get data they weren't supposed to but it shouldn't be a problem for your little test application.
Edit
By the way, one reason why you were probably getting confused by this is that you don't do any error checking on socket() bind() or listen(). The bind() call would certainly return an error and set errno, EINVAL on Linux.
Related
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <pthread.h>
#include <arpa/inet.h>
struct sockaddr_in server, acc;
int sock;
int stuff(void) {
char buffer[2000];
recv(sock, buffer, sizeof(buffer), 0);
send(sock, "HTTP/1.1 200 OK\nContent-Type: text/html\n\nHello", sizeof("HTTP/1.1 200 OK\nContent-Type: text/html\n\nHello"), 0);
shutdown(sock, SHUT_RDWR);
return 0;
}
int main(void) {
int size;
sock = socket(AF_INET, SOCK_STREAM, 0);
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(1111);
if (bind(sock, (struct sockaddr*)&server, sizeof(server)) == -1) {
perror("Error:");
return 1;
}
while (1) {
listen(sock, 5);
sock = accept(sock, (struct sockaddr*)&acc, &size);
printf("accepted\n");
stuff();
close(sock);
}
}
This is meant to be an extremely basic HTTP server.
I don't know what's going wrong, but the connection seems to not end with the client.
Opening this in the browser, it doesn't stop loading and the console is flooded with "accepted" (line 42). No new connections can be accepted.
After your program accepts a connection, it forgets about the socket that listens for new connections, does remember the newly connected socket, does some stuff with that socket, closes it, then tries to accept another connection from the connected socket that it just closed.
There are two problems here:
It's the wrong socket
Even if it was the right socket, it's closed
You create socket number 3 (for example) to wait for new connections. You wait for a connection on socket 3 and the new connection is socket number 4 (for example). Then you do the stuff, then you close socket 4, then you wait for a new connection on socket 4. Do you see the mistake here? Socket 3 is the one that accepts connections.
Since you are not new to programming, you should be able to figure out how to make your program call accept with the right socket.
I made a TCP Client/Server and I can run it one time. But when I try to run it more than one time, it gives me the following error: "Connection refused". Here's my code.
Client
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main() {
int net_socket = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in net_addr;
net_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
net_addr.sin_family = AF_INET;
net_addr.sin_port = htons(3250);
int connection_state = connect(net_socket, (struct sockaddr*)&net_addr, sizeof(net_addr));
if (connection_state == 0) {
printf("Connected with the server.\n");
}
else {
printf("Connection with the server failed. [%s]\n", strerror(errno));
}
char net_message[256];
recv(net_socket, net_message, sizeof(net_message), 0);
close(net_socket);
shutdown(net_socket, SHUT_RDWR);
return 0;
}
Server
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main() {
int net_socket = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in net_addr;
net_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
net_addr.sin_family = AF_INET;
net_addr.sin_port = htons(3250);
bind(net_socket, (struct sockaddr*)&net_addr, sizeof(net_addr));
listen(net_socket, 1);
struct sockaddr_in cl_addr;
int cl_size = sizeof(cl_addr);
int cl_socket = accept(net_socket, (struct sockaddr*)&cl_addr, (socklen_t*)&cl_size);
int loop = 1;
char net_message[256];
send(cl_socket, net_message, sizeof(net_message), 0);
close(net_socket);
close(cl_socket);
shutdown(net_socket, SHUT_RDWR);
shutdown(cl_socket, SHUT_RDWR);
return 0;
}
I've been trying to solve the problem by many ways but I'm a newbie. Thanks for the help in advance!
The problem is with your server lacking the SO_REUSEADDR socket option which leads to the bind() syscall failing. The reason is, that after a client disconnects from the server, the connection is still known by the system in TIME_WAIT state, to wait for late packets. These lead to the bind() to fail with EADDRINUSE if the above mentioned socket option is not set.
Use the following:
...
int one = 1;
setsockopt(net_socket, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
bind(net_socket, (struct sockaddr*)&net_addr, sizeof(net_addr));
...
and do error checks for all syscalls! That would have shown you the problem much earlier and had saved you much time.
Some more issues:
You are sending an uninitialized buffer net_message
A shutdown on a listen socket isn't sensible at all, since no connection is established on it (this here: shutdown(net_socket, SHUT_RDWR);)
The shutdown on the client socket has - if at all - to be performed before the close(cl_socket);. But it is not necessary at all in that case.
How do I achieve 2 way communication on a connected UDP sockets ?
I can send message from client to server, but can not get a message from server. Here is my code. I think that problem must be in the server side, but I don't know how to solve that problem. I have intentionally removed error checking just to post on SO & keep my post short. I am not receiving any errors on any side.
I can get this program running with not connected UDP sockets, but can't with connected socket.
Server.c
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <errno.h>
int main()
{
int sockfd;
struct sockaddr_in me;
char buffer[1024];
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
memset(&me, '\0', sizeof(me));
me.sin_family = AF_INET;
me.sin_port = htons(8080);
me.sin_addr.s_addr = inet_addr("127.0.0.1");
bind(sockfd, (struct sockaddr *)&me, sizeof(me));
recv(sockfd, buffer, 1024, 0);
printf("[+]Data Received: %s\n", buffer);
strcpy(buffer, "Hello Client\n");
send(sockfd, buffer, 1024, 0);
printf("[+]Data Send: %s\n", buffer);
return 0;
}
Client.c
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <errno.h>
int main()
{
int sockfd;
struct sockaddr_in other;
char buffer[1024];
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
memset(&other, '\0', sizeof(other));
other.sin_family = AF_INET;
other.sin_port = htons(8080);
other.sin_addr.s_addr = inet_addr("127.0.0.1");
connect(sockfd, (struct sockaddr *)&other, sizeof(other));
strcpy(buffer, "Hello Server\n");
send(sockfd, buffer, 1024, 0);
printf("[+]Data Send: %s\n", buffer);
recv(sockfd, buffer, 1024, 0);
printf("[+]Data Received: %s\n", buffer);
return 0;
}
Output of Server
[+]Data Received: Hello Server
[+]Data Send: Hello Client
Output of Client
[+]Data Send: Hello Server
// Here it does not receive the message sent by server.
On linux, straceing the executable, the server send does say this:
sendto(3, "Hello Client\n\0\0\0\310$\220\4J\177\0\0\0\0\0\0\0\0\0\0"...,
1024, 0, NULL, 0) = -1 EDESTADDRREQ (Destination address required)
i.e. the server socket indeed does not know the address it needs to send to. Any UDP socket must make the other end of the socket known by either connecting, or providing the destination socket address in sendto.
connect on an UDP socket means just setting a default address for send.
To connect the socket on the "server" side, with an unknown party you should use recvfrom to find out the socket address of the sending party - then you can connect using this address or continue using sendto. With sendto the same socket can communicate with many different parties concurrently.
The TCP server/client sockets are a different case, because listen/accept on the server side returns a new connected socket that is distinct from the original server socket.
I've been playing a bit with the sockets API to get a feel for how it works.
I wrote two little programs:
The server listens on 8080 for a stream connection. It sends anyone that connects to it a simple message.
The client connects to 127.0.0.1:8080, and dumps what it receives to stdout. It repeats this 20000 times in sequence.
The messages flow blazingly fast up to ~16370 times, then it pauses for tens of seconds before it starts moving really fast again to finish out the 20000 connections.
I've repeated this experiment a few times, and I've caught it at 16370, 16371 and 16372. It's surprisingly consistent on repeat experiments.
My question is: why does it need to pause after ~16370 iterations? What's the bottleneck here?
FWIW, I'm on macOS Sierra.
I run the server code like this:
clang -Wall -Werror -Wpedantic server.c -o server.out && ./server.out
and the client code like this:
clang -Wall -Werror -Wpedantic client.c -o client.out && time ./client.out
Here are the two programs:
server.c
#include <errno.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#define PORT 8080
#define MAXMSG 512
int make_socket(int port) {
int sock;
struct sockaddr_in name;
sock = socket(PF_INET, SOCK_STREAM, 0);
if (sock < 0) {
perror("socket");
exit(1);
}
name.sin_family = AF_INET;
name.sin_port = htons(port);
name.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(sock, (struct sockaddr*) &name, sizeof(name)) < 0) {
perror("bind");
exit(1);
}
return sock;
}
int main(int argc, char** argv) {
const char hello[] = "Hello visitor ";
char buffer[MAXMSG];
int sk;
unsigned long count = 0;
strcpy(buffer, hello);
sk = make_socket(PORT);
listen(sk, 10);
printf("ready\n");
for (;;) {
count++;
sprintf(buffer + strlen(hello), "%lu", count);
int s = accept(sk, NULL, NULL);
if (send(s, buffer, strlen(buffer) + 1, 0) < 0) {
perror("send");
exit(1);
}
close(s);
printf("data socket (%d) message sent (%s)\n", s, buffer);
}
}
client.c
#include <arpa/inet.h>
#include <errno.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#define PORT 8080
#define MAXMSG 512
int make_socket() {
int sock;
sock = socket(PF_INET, SOCK_STREAM, 0);
if (sock < 0) {
perror("socket");
exit(1);
}
return sock;
}
int main(int argc, char** argv) {
char buffer[MAXMSG];
int sk;
size_t i;
struct sockaddr_in addr;
strcpy(buffer, "Hello world!");
for (i = 0; i < 20000; i++) {
sk = make_socket();
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
connect(sk, (struct sockaddr*) &addr, sizeof(addr));
recv(sk, buffer, strlen(buffer) + 1, 0);
close(sk);
printf("socket (%d) message = %s\n", sk, buffer);
}
}
This is some of the last stdout I get client side:
socket (3) message = Hello visitor 16369
socket (3) message = Hello visitor 16370
socket (3) message = Hello visitor 16371
socket (3) message = Hello visitor 16372
Most likely you are hitting a limit called the Ephemeral Port Range on your operating system. The same principle applies on all IP based operating systems.
Whenever a socket connection is made a port is allocated for the request and associated with the interface that the connection is made on. Once this socket is closed the port is put into a state called TIME_WAIT. Effectively putting the port on the bench for a period of time to ensure that is it not reused too soon. This is to prevent latent packets in the internet from coming in late and causing issues.
The ephermal port range is specified on Linux as /proc/sys/net/ipv4/ip_local_port_range.
You can display these on MacOS using:
sysctl net.inet.ip.portrange.first net.inet.ip.portrange.last
net.inet.ip.portrange.first: 49152
net.inet.ip.portrange.last: 65535
Which is 16,383 available ports in the ephemeral range.
To see all network parameters you can execute:
sysctl net.inet.tcp
You can change the TIME_WAIT values but for your high stress application it would simply lower the threshold at which your slowdown waits.
You can see the number of open connections using netstat -an. Sockets may be stuck in TIME_WAIT state if you are opening and closing a lot of connections. In some places this is unavoidable, but you may need to consider if you need a pool of connection if this is the case.
If TIME_WAIT is the issue there are system settings you can adjust. you can set net.ipv4.tcp_tw_reuse / net.ipv4.tcp_tw_recycle to speed up connection turnover.
One quick test would be to switch to another interface and try again. If you were using localhost and then experienced the slowdown you could then switch to your external IP on another interface and you should run like gangbusters until you hit the limit again.
This is not an issue with the language your using but an issue in socket based network usage.
You are probably dealing with the TIME_WAIT state of the sockets. After actively closing each connection socket in your server, the socket remains in that state for a long (tens of seconds) period. So, as #Blaze suggests, your program is reaching a resource limit and has to wait for this sockets to be definitively closed.
This feature is there to prevent two cases, the first is the chance that a delayed packet sent in one connection to be interpreted as part of a later connection. The second is the chance that the last ACK of the connection close is not received by the passive closing side of the connection, causing it to retransmit the FIN/ACK. If this happens and the active closing side has already closed the socket it will answer with a RST, causing the other side to receive an error in spite that all the information was correctly sent.
Take a look at this: http://www.serverframework.com/asynchronousevents/2011/01/time-wait-and-its-design-implications-for-protocols-and-scalable-servers.html
If you really want to completely close the socket (having the risk of the previous events to happen) you have to tune the SO_LINGER option before trying to close it.
struct linger immediate_linger;
immediate_linger.l_onoff = 1; /* Do linger on closing */
immediate_linger.l_linger = 0; /* Wait 0 seconds to linger after closing */
if (setsockopt(comm_socket, SOL_SOCKET, SO_LINGER, &immediate_linger, sizeof (immediate_linger))) {
err = errno;
printf("Error setting immediate linger for socket %d: %s.", comm_socket, strerror(err));
}
else {
printf("Set immediate linger after close for the socket %d.", comm_socket);
}
I am reading a book on sockets in c and am making a very simple server program. I copied the code verbatim. There is nothing trying to connect to this server program yet and have change the port multiple times to make sure.
The program is failing on the accept method on the first run of the loop. From what I read in the man pages, accept is supposed to block the caller until a connection is made, and not fail if there aren't connections in the queue like it is doing. Is there any reason accept would be returning a value less than 0? I will post the code up to where it fails:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
//Max number of outstanding connection requests
#define MAXPEDNING 5
#define NONE
#define BUFSIZE 1024
int main(int argc, char **argv)
{
in_port_t servPort;
#ifdef CMDLINE
if(argc != 2)
{
puts("Error! Usage is <Server Port>");
return 0;
}
servPort = atoi(argv+1);
#endif //CMDLINE
#ifdef NONE
servPort = 2549;
#endif //NONE
int servSock;
if((servSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
{
puts("socket() failed");
return 0;
}
struct sockaddr_in servAddr;
memset(&servAddr, 0, sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
servAddr.sin_port = htons(servPort);
printf("Port in network order: %d\nPort in host order:%d\n", servAddr.sin_port, ntohs(servAddr.sin_port));
if((bind(servSock, (struct sockaddr*) &servAddr, sizeof(servAddr)))<0)
{
puts("bind failed");
return 0;
}
while(1)
{
struct sockaddr_in clntAddr;
socklen_t clntAddrLen = sizeof(clntAddr);
int clntSock = accept(servSock, (struct sockaddr*) &clntAddr, &clntAddrLen);
if(clntSock < 0)
{
puts("accept failed");
return 0;
}
It reaches the accept failed and quits. The only thing that is odd about my setup is that I am on a Debian VM (VirtualBox) and I am wondering if network operations are handled in a weird way. I shouldn't be even trying to accept anything because there are no connections.
You need to call listen() in between bind() and accept().