Reputation: 2181
I'm looking forward to achive this: Server recieves from number of clients a string(file name) which he has to take from the folder and return it to the the client by a bufferSize which is defined from the command line. It has to be implemented with UDP communication. i'm familiarized with TCP sockets, but i don't get how can i get a fileDescriptor for the udp connection since accepts is missing.
So I'm thinking about this: after the config i do a while-loop in the server where i get 'some kind of descriptor' which i'll send to a new thread which knows where to send the data back... Any ideas?
I've checked the net but didn't found a concrete explanation for this kind of operation.
Upvotes: 5
Views: 31301
Reputation: 753455
You don't get connections with UDP; you use sendto()
and recvfrom()
to send and receive messages.
So the server will call recvfrom()
on the socket; unwrap the request from the data it receives, do the appropriate actions, and use sendto()
to send the response back to the client from which the request was received.
The client will call sendto()
to package a message to the server, and then call recvfrom()
to get the response. Note that UDP is an unreliable protocol; there is no guarantee that each message will be delivered. The client has to implement timeouts in case the server dropped a UDP request. Servers have to be able to deal with duplicate requests, too.
Upvotes: 5
Reputation: 2181
I have finally found something helpful, maybe it will be useful for others so here it is: the code is commented and really clear. PS: sorry for the long paste, but google doesn't let me copy the link.
/*
* udpserver.c - A simple UDP echo server
* usage: udpserver <port>
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define BUFSIZE 1024
/*
* error - wrapper for perror
*/
void error(char *msg) {
perror(msg);
exit(1);
}
int main(int argc, char **argv) {
int sockfd; /* socket */
int portno; /* port to listen on */
int clientlen; /* byte size of client's address */
struct sockaddr_in serveraddr; /* server's addr */
struct sockaddr_in clientaddr; /* client addr */
struct hostent *hostp; /* client host info */
char buf[BUFSIZE]; /* message buf */
char *hostaddrp; /* dotted decimal host addr string */
int optval; /* flag value for setsockopt */
int n; /* message byte size */
/*
* check command line arguments
*/
if (argc != 2) {
fprintf(stderr, "usage: %s <port>\n", argv[0]);
exit(1);
}
portno = atoi(argv[1]);
/*
* socket: create the parent socket
*/
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
/* setsockopt: Handy debugging trick that lets
* us rerun the server immediately after we kill it;
* otherwise we have to wait about 20 secs.
* Eliminates "ERROR on binding: Address already in use" error.
*/
optval = 1;
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
(const void *)&optval , sizeof(int));
/*
* build the server's Internet address
*/
bzero((char *) &serveraddr, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
serveraddr.sin_port = htons((unsigned short)portno);
/*
* bind: associate the parent socket with a port
*/
if (bind(sockfd, (struct sockaddr *) &serveraddr,
sizeof(serveraddr)) < 0)
error("ERROR on binding");
/*
* main loop: wait for a datagram, then echo it
*/
clientlen = sizeof(clientaddr);
while (1) {
/*
* recvfrom: receive a UDP datagram from a client
*/
bzero(buf, BUFSIZE);
n = recvfrom(sockfd, buf, BUFSIZE, 0,
(struct sockaddr *) &clientaddr, &clientlen);
if (n < 0)
error("ERROR in recvfrom");
/*
* gethostbyaddr: determine who sent the datagram
*/
hostp = gethostbyaddr((const char *)&clientaddr.sin_addr.s_addr,
sizeof(clientaddr.sin_addr.s_addr), AF_INET);
if (hostp == NULL)
error("ERROR on gethostbyaddr");
hostaddrp = inet_ntoa(clientaddr.sin_addr);
if (hostaddrp == NULL)
error("ERROR on inet_ntoa\n");
printf("server received datagram from %s (%s)\n",
hostp->h_name, hostaddrp);
printf("server received %d/%d bytes: %s\n", strlen(buf), n, buf);
/*
* sendto: echo the input back to the client
*/
n = sendto(sockfd, buf, strlen(buf), 0,
(struct sockaddr *) &clientaddr, clientlen);
if (n < 0)
error("ERROR in sendto");
}
}
Upvotes: 3