So I have a device connected to my network card and it sends data to port 11678 and address 192.168.121.1 using IPv4 and UDP. I have checked that the device does actually send to that port and address using IPv4 and UDP by calling tcpdump. However my C socket does not receive any packets. Below I have a minimum non-working example that just runs an infinite loop until one packet is received. It does not receive any packets even though tcpdump does, so I assume something is wrong with my code.
#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 <unistd.h>
#define DEST_ADDR "192.168.121.1"
#define DEST_PORT 11678
#define PACKET_MAXSIZE 1024
int main(int argc, char **argv) {
struct sockaddr_in dest_addr;
bzero(&dest_addr, sizeof(dest_addr));
dest_addr.sin_family = AF_INET;
/* create socket */
int fd = socket(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK, 0); // use SOCK_NONBLOCK?
if (fd < 0) {
perror("Could not create socket.");
}
/* bind port and address to socket */
dest_addr.sin_port = htons(DEST_PORT);
inet_aton(DEST_ADDR, &dest_addr.sin_addr);
int rc = bind(fd, (struct sockaddr*) &dest_addr, sizeof(dest_addr));
if (rc != 0) {
perror("Could not bind socket to local address");
}
/* read packets */
void* buf;
posix_memalign(&buf, 4096, 1024);
while (true) {
ssize_t read_size = read(fd, buf, PACKET_MAXSIZE);
printf("%d\n", read_size);
if (read_size > 0) {
break;
}
}
return 0;
}
The read just returns -1 and sets errno to 11 (EAGAIN) in every iteration. Any help is appreciated. Thanks in advance.
If you're on a system that uses iptables, check that you aren't dropping packets. tcpdump will show packets that are incoming before they get to iptables.
Another thing is that you should be using epoll or select to read from the socket in a more controlled way. EAGAIN isn't neccessarily wrong: it just means there's no data. But you're whizzing round that while loop without waiting, so I'd expect lots of EAGAIN's until something actually arrives at the port.
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.
This is my first time socket programming and have a question about send and recv. I'm sending a file from server to client which works fine. But, when I want to continue my program with more send() and recv() calls (the commented code at the end of client and server), the client receives this data and writes it to newfile.txt.
So, my question is, how do I call send() from the server to only send data from test.txt, and then recv() on the client to only receive and write data from test.txt to newfile.txt? After this, I would want to continue with my program with more send() and recv() calls which dont get mixed up with the file transfer code.
Client:
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>
int main(int argc, char *argv[]){
int port = 8001;
int client_socket;
struct sockaddr_in server_addr;
int connect_status;
client_socket = socket(AF_INET, SOCK_STREAM, 0); //SOCK_STREAM for TCP
if (client_socket < 0)
{
printf("Error creating socket\n");
exit(1);
}
printf("Socket created\n");
//address for socket to connect to
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port); //8001 arbitrary port
server_addr.sin_addr.s_addr = INADDR_ANY;
//connect to address of socket
connect_status = connect(client_socket, (struct sockaddr *) &server_addr, sizeof(server_addr));
if(connect_status == -1)
{
printf("Error connecting to server\n");
exit(1);
}
printf("Connected to Server\n");
FILE* fp = fopen( "newfile.txt", "w");
char data[512];
int b;
while((b=recv(client_socket, data, 512,0))>0){
fwrite(data, 1, b, fp);
}
fclose(fp);
//recv(client_socket, data, 512,0);
//printf("client buffer: %s\n", data);
close(client_socket);
return 0;
}
Server:
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
int main(int argc, char *argv[]){
int port = 8001;
int server_socket;
struct sockaddr_in server_addr;
int client_socket, client_addr;
int bind_status, listen_status;
server_socket = socket(AF_INET, SOCK_STREAM, 0); //SOCK_STREAM for TCP
if (server_socket < 0)
{
printf("Error creating socket\n");
exit(1);
}
printf("Socket created\n");
//address for socket to connect to
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);
server_addr.sin_addr.s_addr = INADDR_ANY;
//bind socket to the IP and port
bind_status = bind(server_socket, (struct sockaddr *) &server_addr, sizeof(server_addr));
if (bind_status < 0)
{
printf("Error binding to socket\n");
exit(1);
}
printf("Socket binded\n");
//listen for client connections
listen_status = listen(server_socket, 10);
if (listen_status == -1)
{
printf("Error listening to socket\n");
exit(1);
}
printf("Listening\n");
//accept client connection
socklen_t addr_len;
addr_len = sizeof(client_socket);
client_socket = accept(server_socket, (struct sockaddr *) &client_addr, &addr_len);
FILE *fp = fopen("test.txt", "r");
char data[512];
int b;
while((b = fread(data, 1, 512, fp))>0){
send(client_socket, data, b, 0);
}
fclose(fp);
// strcpy(data,"test message");
//printf("server buffer: %s\n", data);
//send(client_socket, data, 512, 0);
close(server_socket);
return 0;
}
You need some way to indicate the server that you have finished sending a file, and now you want to send another thing.
While the socket abstraction seems to show you that the recv and send calls are somehow synchronized, this means that the data you send from the client in one call to send is recv'd in the server with exactly one recv, that is not true, due fundamentally to how the sockets are implemented (the client tcp can decide to split your transfer in several packets, and the unattending of the server can make all those packets to buffer n the receiver before the server receives part of them in one call to recve and others in the text call.
The only thing sure is that a byte that has been sent before, is receive before, and no repeated or missing bytes in between. But the number of bytes received at some recve call is dictated only by the amount of buffered data that one side of the connection has.
This means that, for telling the server that you are finished with your file and some other thing is to be sent, you must do something that allows the server to recognize that the data has ended and more data on a different thing is about to come.
There are several approaches here... you can send an inband sequence (some control sequence) that, wen read in the other side, will be recognized as the end of a block of data and the beginning of the next. Some systems use a packet encoding that simply prepends each block with a number of bytes to follow, and an empty packet (e.g. a single number 0, meaning 0 bytes to follow) can represent this sequence. Another way, can be to use a specific sequence you know is improbable to occur in the data (e.g. \n.\m, two newlines with one dot interspersed ---this has been used many times in unix's ed editor, for example, or the post office protocol uses it.) and if it is the case that such a sequence happens to be in the file, just double the dot, to indicate that it is not the separator sequence. And both ends must agree on this (so called) protocol.
Other mechanisms are valid, you can close the connection and use another socket for a new data exchange.... for example, FTP protocol uses this approach by using one control connection for FTP commands, while using other connections for data transfers.
I have not included code because there are plenty of examples in the literature. Try to get access to the book "Unix Network Programming" of Richard W. Stevens. That's a very good reference to get initiated on socket protocols and how to deal with all these things.
I am implementing DPLPMTUD and I want to suppress the Linux kernel from returning -1 with errno = EMSGSIZE when I send UDP packet longer than the local interface's MTU. I want to avoid the pain of dealing with error handling when several datagrams are sent out (especially when using sendmmsg(2)), each perhaps belonging to a different connection. I'd rather have the kernel drop the packet and let the application DPLPMTUD logic figure out the MTU.
ip(7) has this to say:
It is possible to implement RFC 4821 MTU probing with SOCK_DGRAM
or SOCK_RAW sockets by setting a value of IP_PMTUDISC_PROBE
(available since Linux 2.6.22). This is also particularly use‐
ful for diagnostic tools such as tracepath(8) that wish to de‐
liberately send probe packets larger than the observed Path MTU.
Yet setting this option does not produce the desired effect. Here is the code to illustrate the problem:
/* emsgsize.c: test whether IP_PMTUDISC_PROBE suppresses EMSGSIZE
*
* Usage: emsgsize packet_size
*/
#include <arpa/inet.h>
#include <errno.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#define CHECK(w_, s_) do { if ((s_) < 0) { perror(w_); return 1; }} while (0)
/* Payload */
static unsigned char data[64 * 1024];
int
main (int argc, char **argv)
{
int fd, on, s, size;
struct sockaddr_in si;
ssize_t sent;
if (argc != 2)
{
fprintf(stderr, "usage: emsgsize size\n");
return 1;
}
size = atoi(argv[1]);
memset(&si, 0, sizeof(si));
si.sin_family = AF_INET;
fd = socket(si.sin_family, SOCK_DGRAM, 0);
CHECK("socket", fd);
s = bind(fd, (struct sockaddr *) &si, sizeof(si));
CHECK("bind", s);
/* This is supposed to suppress sendmsg(2) returning -1 with
* errno = EMSGSIZE, see ip(7):
*
" It is possible to implement RFC 4821 MTU probing with SOCK_DGRAM
" or SOCK_RAW sockets by setting a value of IP_PMTUDISC_PROBE
" (available since Linux 2.6.22). This is also particularly use-
" ful for diagnostic tools such as tracepath(8) that wish to de-
" liberately send probe packets larger than the observed Path MTU.
*/
on = IP_PMTUDISC_PROBE;
s = setsockopt(fd, IPPROTO_IP, IP_MTU_DISCOVER, &on, sizeof(on));
CHECK("setsockopt", s);
memset(&si, 0, sizeof(si));
si.sin_family = AF_INET;
si.sin_port = htons(12345); /* Destination does not matter */
s = inet_pton(AF_INET, "127.0.0.1", &si.sin_addr);
CHECK("inet_pton", s);
sent = sendto(fd, data, (size_t) size, 0, (struct sockaddr *) &si,
sizeof(si));
CHECK("sendto", sent);
return 0;
}
When I send packets larger than the MTU, sendto() above returns -1 and errno is set to EMSGSIZE -- exactly what I want to avoid.
Is there a way to do what I want?
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 know that this is obviously elementary question and I know that there are many tutorials and ready-to-go examples but I must missing something. I am trying to send for example text (char *) via UDP socket to other machine in local network. So far I tried some tutorials like http://gafferongames.com/networking-for-game-programmers/sending-and-receiving-packets/ and so on but I always get error in bind() function with errno "Cannot assign requested address".
I just have some data in char array and I want to push them via network to another host. Could someone please point me to the right direction? Do I need socket server or client? Do I need to bind the socket to some interface?
This is my playground:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <errno.h>
int handle;
int init_socket()
{
handle = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (handle <= 0)
{
printf("failed to create socket\n");
return 1;
}
printf("sockets successfully initialized\n");
return 0;
}
int main ()
{
unsigned short port = 30000;
char * data = "hovno";
init_socket();
struct sockaddr_in address;
memset((char *) &address, 0, sizeof(address));
address.sin_family = AF_INET;
address.sin_addr.s_addr = inet_addr("192.168.11.129"); // this is address of host which I want to send the socket
address.sin_port = htons(port);
printf("handle: %d\n", handle); // prints number greater than 0 so I assume handle is initialized properly
if (bind(handle, (const struct sockaddr*) &address, sizeof(struct sockaddr_in)) < 0)
{
printf("failed to bind socket (%s)\n", strerror(errno)); // Cannot assign requested address
return 1;
}
int nonBlocking = 1;
if (fcntl(handle, F_SETFL, O_NONBLOCK, nonBlocking) == -1)
{
printf("failed to set non-blocking\n");
return 2;
}
int sent_bytes = sendto(handle, data, strlen(data), 0, (const struct sockaddr*) &address, sizeof(struct sockaddr_in));
if (sent_bytes != strlen(data))
{
printf("failed to send packet\n");
return 3;
}
return 0;
}
bind is called for the local address (one you intend to recv packets to). The IP address must be a local IP address of the machine, or (most frequently) INADDR_ANY.
Normally you don't have to use bind on the client side at all. The system will pick a suitable free port for you automatically.
To specify the remote address for a UDP socket, use sendto, not send.
If you search Google for udp client c code, one of the first results is this one. You can see that the networking part is basically just two calls, socket and sendto.