I'm working on a homework problem for class. I want to start a UDP Server that listens for a file request. It opens the file and sends it back to the requesting client with UDP.
Heres the server code.
// Create UDP Socket
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
perror("Can't create socket");
exit(-1);
}
// Configure socket
memset(&server, 0, sizeof server);
server.sin_family = AF_INET; // Use IPv4
server.sin_addr.s_addr = htonl(INADDR_ANY); // My IP
server.sin_port = htons(atoi(argv[1])); // Server Port
// Bind socket
if ((bind(sockfd, (struct sockaddr *) &server, sizeof(server))) == -1) {
close(sockfd);
perror("Can't bind");
}
printf("listener: waiting to recvfrom...\n");
if (listen(sockfd, 5) == -1) {
perror("Can't listen for connections");
exit(-1);
}
while (1) {
client_len = sizeof(struct sockaddr_in);
newsockfd = accept(sockfd, (struct sockaddr*)&client,&client_len);
if (newsockfd < 0) {
perror("ERROR on accept");
}
// Some how parse request
// I do I use recv or recvfrom?
// I do I make new UDP socket to send data back to client?
sendFile(newsockfd, filename);
close(newsockfd);
}
close(sockfd);
I'm kind of lost how do I recv data from the client? And how to I make a new UDP connection back to the client?
How UDP is different from TCP:
message-oriented, not stream-oriented. You don't read/write or send/recv. You sendto/recvfrom. The size of message is limited to 64K. Each call to recvfrom gets one message sent by a call to sendto. If recvfrom passes a buffer that's smaller than the size of message, the rest of message is gone for good.
no connections. Therefore no listen/accept/connect. You send a message to a particular address/port. When you receive message (on the address/port to which your socket is bound), you get the source of the incoming message as an output parameter to recvfrom.
no guarantees. The messages can be dropped or received out of order. If I remember correctly, they cannot be truncated, though.
One last word of caution - you may find yourself re-inventing TCP over UDP. In that case, stop and go back to TCP.
I have written a UDP server-client in C , where the client sends a registration number and the server gives a name as the feedback.
SERVER
0. Variable initialization
1. sock()
2. bind()
3. recvfrom()
4. sendto()
CLIENT
0. gethostbyname()
1. sock()
2. bzero()
4. sendto()
5. recvfrom()
Hope it helps. You can find the example code here udp server/client
accept is only used for connection oriented (STREAM) sockets. UDP is not stream, oriented, so there are no connections and you can't use accept(2) -- it will return EOPNOTSUPP.
Instead, you just read packets directly from the bound service socket (generally using recvfrom(2) so you can tell where thy came from, though you can use recv or just read if you don't care), afterwhich you can send packets back using the same socket (and generally using sendto(2))
Keep in mind that UDP is connectionless. It only sends packets, and is not suitable for sending files - unless the entire content fit in one UDP packet.
If you anyway want to send/receive UDP packets, you simply call sendto/recvfrom with the appropriate addresses.
Related
Just for the purpose of learning raw sockets in C I am writing a simple server that uses raw sockets to receive and send messages.
I create the socket
if ((r_sock = socket(AF_INET, SOCK_RAW, IPPROTO_UDP))< 0){
perror("socket");
exit(-1);
}
Then I create an infinite loop and start receiving, processing, and replying
while(1){
if((n = recvfrom(r_sock, buffer, BUFLEN, 0, (struct sockaddr *) &client, &client_len))<0){
perror("recvfrom");
exit(-1);
}
// Discard messages not intended to the server
if(htons(udp->uh_dport) != my_port){
continue;
}
//Do whatever with the data received and then send reply to client
// ....
if((n = sendto(r_sock, udp, ntohs(udp->uh_len), 0, (struct sockaddr *) &client, client_len))<0){
perror("sendto");
exit(-1);
}
}
I am not showing here the definition of every single variable but for the sake of completeness, buffer is a char array of size BUFLEN (big enough) and udp is a struct udphdr pointer to the right position in the buffer.
The point is that I have another program that serves as client using standard UDP sockets (SOCK_DGRAM) which is proved to be working properly (I also tried with netcat just in case). When I send a message with the client, it never receives the reply back. It seems that when the server sends the reply to the client, the server itself gets the message and the client gets nothing.
So, my question is: is there a way of solving this with raw sockets? That is, to make the server not receive its own messages and preventing others from receiving them?
Thanks in advance!
I have just realised that it was a problem with the checksum... Once I had a correct checksum in UDP the packet was correctly received by the client.
Wireshark gave me the lead to the solution. I saw that the checksum was not validated so I went to Edit > Preferences > Protocols > UDP > Validate the UDP checksum if possible and checked it.
Hope it helps
I have a forking HTTP proxy implemented on my Ubuntu 14.04 x86_64 with the following scheme (I'm reporting the essential code and pseudocode just to show the concept):
socketClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
bind(socketClient,(struct sockaddr*)&addr, sizeof(addr));
listen(socketClient, 50);
newSocket = accept(socketClient, (struct sockaddr*)&cliAddr, sizeof(cliAddr));
get request from client, parse it to resolve the requested hostname in an IP address;
fork(), open connection to remote server and deal the request;
child process: if it is a GET request, send original request to server and while server is sending data, send data from server to client;
child process: else if it is a CONNECT request, send string 200 ok to client and poll both client socket descriptor and server socket descriptor with select(); if I read data from server socket, send this data to client; else if I read data from client socket, send this data to server.
The good thing is that this proxy works, the bad thing is that now I must collect statistics; this is bad because I'm working on a level where I can't get the data I'm interested in. I don't care about the payload, I just need to check in IP and TCP headers the flags I care about.
For example, I'm interested in:
connection tracking;
number of packets sent and received.
As for the first, I would check in the TCP header the SYN flag, SYN/ACK and then a last ACK; as for the second, I would just do +1 to a counter of mine every time a char buffer[1500] is filled with data when I send() or recv() a full packet.
I realized that this is not correct: SOCK_STREAM doesn't have the concept of packet, it is just a continuous stream of bytes! The char buffer[1500] I use at point 7. and 8. has useful statistic, I may set its capacity to 4096 bytes and yet I couldn't keep track of the TCP packets sent or received, because TCP has segments, not packets.
I couldn't parse the char buffer[] looking for SYN flag in TCP header either, because IP and TCP headers are stripped from the header (because of the level I'm working on, specified with IPPROTO_TCP flag) and, if I understood well, the char buffer[] contains only the payload, useless to me.
So, if I'm working on a too high level, I should go lower: once I saw a simple raw socket sniffer where an unsigned char buffer[65535] was cast to struct ethhdr, iphdt, tcphdr and it could see all the flags of all the headers, all the stats I'm interested in!
After the joy, the disappointment: since raw sockets work on a low level they don't have some concepts vital to my proxy; raw sockets can't bind, listen and accept; my proxy is listening on a fixed port, but raw sockets don't know what a port is, it belongs to the TCP level and they bind to a specified interface with setsockopt.
So, if I'd socket(PF_INET, SOCK_RAW, ntohs(ETH_P_ALL)) I should be able to parse the buffer where I recv() and send() at .7 and .8, but I should use recvfrom() and sendto()...but all this sounds quite messy, and it envolves a nice refactoring of my code.
How can I keep intact the structure of my proxy (bind, listen, accept to a fixed port and interface) and increase my line of vision for IP and TCP headers?
My suggestion is to open a raw socket in, for example, another thread of your application. Sniff all traffic and filter out the relevant packets by addresses and port numbers. Basically you want to implement your own packet sniffer:
int sniff()
{
int sockfd;
int len;
int saddr_size;
struct sockaddr saddr;
unsigned char buffer[65536];
sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
if (sockfd < 0) {
perror("socket");
return -1;
}
while (1) {
saddr_size = sizeof(saddr);
len = recvfrom(sockfd, buffer, sizeof(buffer), 0, &saddr, &saddr_size);
if (len < 0) {
perror("recvfrom");
close(sockfd);
return -1;
}
// ... do the things you want to do with the packet received here ...
}
close(sockfd);
return 0;
}
You can also bind that raw socket to a specific interface if you know which interface is going to be used for the proxy's traffic. For example, to bind to "eth0":
setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, "eth0", 4);
Use getpeername() and getsockname() function calls to find the local and remote addresses and port numbers of your TCP connections. You'll want to filter the packets by those.
int udp_sock() {
//Create socket
sock = socket(AF_INET , SOCK_DGRAM , 0);
if (sock == -1) {
printf("Could not create socket\n");
}
puts("Socket created.......\n");
server1.sin_addr.s_addr = inet_addr("172.210.110.10");
server1.sin_family = AF_INET;
server1.sin_port = htons(PORT);
//Connect to remote server
con= connect(sock , (struct sockaddr *)&server1 , sizeof(server1));
if(con<0) {
perror("connect failed. Error\n");
return con;
}
puts("Connected\n");
return 0;
}
The packet is reaching server mentioned, but the error "destination port unreachable" comes up in Wireshark.
How to assign a UDP port on my client to receive data on a particular port?
How to assign two different ports - 1024 and 1025 to receive data?
Any suggestions will be helpful.
There needs to be a server waiting on the other end. A simple way for testing is to use netcat.
nc -lu 8053
Alternatively set up a utility that is designed for udp testing, such as echo server. This is normally built into an inetd or xinetd server
If you want to intercept incoming udp packets you will need to use bind() select()/poll()/epoll() and recvfrom()
I am making a web proxy using sockets in C. Basically, I listen to a given port number, take in an HTML request from it, make the request, and then send what I get back where it came from.
I've got the first part working. I'm able to read in the request and send it to the necessary web server, and I get a valid response. I'm just not sure how to send that response to the port where it was asked for.
(I'm testing my code using Netcat to make the request and get a response back, and at the moment the response I am trying to send is not being printed by Netcat.)
Here's my relevant code:
struct sockaddr_in port;
bzero((char *) &port, sizeof(port));
port.sin_family = AF_INET;
port.sin_port = htons(atoi(argv[1]));
port.sin_addr.s_addr = INADDR_ANY;
int socket;
int acceptSocket;
char response[RESPONSE_SIZE];
socket = Socket(AF_INET, SOCK_STREAM, 0);
Bind(socket, (struct sockaddr *) &port, sizeof(port));
Listen(socket, 0);
acceptSocket = Accept(socket, NULL, NULL);
if (acceptSocket >= 0)
printf("Connection open on port %s\n", argv[1]);
if (!ForwardHTTPRequest(acceptSocket, response))
printf("Forward error\n");
shutdown(socket, 0);
Connect(socket, (struct sockaddr *) &port, sizeof(port));
Send(socket, response, strlen(response), 0);
The last three lines are my attempt to send the response back. I shut down the read side of the socket, connect in order to send, and then send. This isn't producing any response though.
acceptSocket is the socket you're using for communications one the session is established. Just send a message back on that socket before you shut it down.
It's unusual to shut down the controlling socket unless you're absolutely sure you don't want to serve any more requests. The basic workflow of a server is:
create listensocket
bind listensocket
while working:
worksocket = accept listensocket
read and write to worksocket as much as you want
close worksocket
shutdown/close listensocket
(although, for responsiveness, the actual work done on worksocket is farmed off to a different thread or process, so that the server can handle subsequent requests without waiting).
I am writing UDP server and client in C on UNIX. I need to handle each client in its own thread on server. In each thread, I want to receive only messages from corresponding client. Right now I am peeking messages using recvfrom and checking message whether it is "mine".
I heard that it is possible to have multiple sockets listening on the same host:port and connect each of them to corresponding client so it will receive messages only from the said client. Here is the code I run when I run into new client. However, after first client connects messages are in fact filtered, but not only on new socket, but also on main socket listening for new clients, so I cant connect new clients.
void fun(int* sockfd, struct sockaddr_in* my_addr, struct sockaddr_in* cli_addr)){
if ((*sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
ERR("socket");
}
int optval = 1;
bzero(my_addr, sizeof (*my_addr));
my_addr->sin_family = AF_INET;
my_addr->sin_port = htons(PORT);
my_addr->sin_addr.s_addr = htonl(INADDR_ANY);
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof (optval)) < 0) {
ERR("setsockopt");
}
if (bind(sockfd, (struct sockaddr*) my_addr, sizeof (*my_addr)) == -1) {
ERR("bind");
}
if (connect(*socket, (struct sockaddr*) cli_addr, sizeof (*cli_addr)) < 0)
ERR("connect");
}
}
Is there a better (and working) way to filter UDP messages?
In my opinion you should use one thread for receiving and sending data and then dispatch to the other threads.
There is no need for more than one socket server side. One socket receive all datagrams, you process them by extracting the source, and then dispatch it.
You could do something like this:
Datagram is read:
source is known, call the backback you have for it
source is not known, create a new thread, and register a callback for this source.
Whenever you want to "disconnect" a client, unregister the callback and remove the thread.
Note that by "disconnect" I mean in a logical way for your application, since UDP socket are not connected.