I am currently doing a client / server application in C that words over the internet.The server is to keep listening for new connections from the clients. Currently I am listening to cllients, but once a client connects, the server wont keep on listening for further clients. The following depicts the server side code to connect with a client:
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in sockaddr, cliaddr;
bzero(&sockaddr, sizeof(struct sockaddr_in));
bzero(&cliaddr, sizeof(struct sockaddr_in));
sockaddr.sin_family = AF_INET;
sockaddr.sin_addr.s_addr = INADDR_ANY;
sockaddr.sin_port = ntohs(atoi(argv[1]));
if(bind(sockfd, (struct sockaddr *) &sockaddr, sizeof(sockaddr)) <0) {
printf("error binding socket: %d\n", errno);
exit(1);
}
printf("binded to %d : %d\n", sockaddr.sin_addr.s_addr, htons(sockaddr.sin_port));
listen(sockfd,5);
socklen_t clilen = sizeof(cliaddr);
int newsockfd = accept(sockfd, (struct sockaddr *) &cliaddr, &clilen);
if (newsockfd < 0)
error("ERROR on accept");
printf("server connected to %d:%d\n", cliaddr.sin_addr.s_addr, htons(cliaddr.sin_port));
I am assuming i have to create some form of threads that will fork once a connection has been established. But i dont know how to implement it..
Any help is greatly appreciated
Following points might help:
You should have your accept call in a loop, so that after accepting one connection, it can go back again to accept more connections.
To process each of the connections seperately, you can create threads using pthread_create or some similar thread creation APIs.
You can choose to use Non-Blocking sockets using which you can process multiple-connections in the same thread easily.
You can collect the following Book to learn and understand how to develop concurrent server in C. It is hard to explain with examples various ways of writing concurrent server in the answer. The source codes of the examples in the book are downloadable so you can try them out even without the book (you will find in the same URL). Study the code and you will see how things work.
UNIX Network Programming, Volume 1, Second Edition: Networking APIs: Sockets and XTI
This book covers almost all the things you want to know about socket programming.
Related
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.
I'm learning from the book Hacking, the Art of Exploitation by Jon Erickson, and I am confused regarding to a simple code sample that he provided. The code is to set up a simple server, but when I complied it (no error) and ran the code, it hangs
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "hacking.h"
#define PORT 7890 // the port users will be connecting to
int main(void) {
int sockfd, new_sockfd; // listen on sock_fd, new connection on new_fd
struct sockaddr_in host_addr, client_addr; // my address information
socklen_t sin_size;
int recv_length=1, yes=1;
char buffer[1024];
if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1)
fatal("in socket");
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
fatal("setting socket option SO_REUSEADDR");
host_addr.sin_family = AF_INET; // host byte order
host_addr.sin_port = htons(PORT); // short, network byte order
host_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP
memset(&(host_addr.sin_zero), '\0', 8); // zero the rest of the struct
if (bind(sockfd, (struct sockaddr *)&host_addr, sizeof(struct sockaddr)) == -1)
fatal("binding to socket");
if (listen(sockfd, 5) == -1)
fatal("listening on socket");
while(1) { // Accept loop
sin_size = sizeof(struct sockaddr_in);
new_sockfd = accept(sockfd, (struct sockaddr *)&client_addr, &sin_size);
if(new_sockfd == -1)
fatal("accepting connection");
printf("server: got connection from %s port %d\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
send(new_sockfd, "Hello World!\n", 13, 0);
recv_length = recv(new_sockfd, &buffer, 1024, 0);
while(recv_length > 0) {
printf("RECV: %d bytes\n", recv_length);
dump(buffer, recv_length);
recv_length = recv(new_sockfd, &buffer, 1024, 0);
}
close(new_sockfd);
}
return 0;
}
I did a little printf() to find out where I hangs, and it turns out to be on this line
sin_size = sizeof(struct sockaddr_in);
I'm not sure if it has to do with my environment, or there is something that I am missing. The environment that the book uses can no longer be updated (some old verson of Ubuntu). So I am currently using the latest one.
Can someone please explain to me why the program does not work?
And if there is some basic that need to know before learning the network chapter, please do tell.
This program won't proceed until accept on the line after the sizeof receives an incoming connection from a client program. Your printf shows that accept was called but was blocked.
You need to compile and run the client with the right options (IP / Port) to connect to this server program.
Update
If 192.168.42.248 is from the book, then you're probably trying to connect to the wrong IP. Try telnet 127.0.0.1 7890.
It's a server, it will "hang" until you make a connection to port 7890. That's the whole point of the program (for more detais, it blocks since accept() is waiting for a connection)
Assuming you are running unix, try to type echo "hi there" | nc localhost 7890 in a terminal from the same machine while you run it, and you will see how it "unblocks"
Telling by all the comments flying around in your thread I'd recommend to connect with telnet using the following command line: telnet localhost 7890
telnet takes as arguments the host to connect to and the port to connect to on this host. Using "localhost" is similar to using the loopback IP 127.0.0.1.
Why does connecting to the server solve the "hang"? accept is blocking as you can read in the man page or any other documentation of your programming environment. This means the function won't return until a client connects. After connecting the function returns a handle to the socket created for the connecting client which can be used to communicate.
Here's the deal, I'm writing a simple tcp socket server in C (with unix system calls) that I'm not able to get to accept connections.
From what I can tell, I get through the server initialization just fine, but when I try to connect to the port that I print out (see code below) it refuses as if nothing is there.
More to the point, when I netstat that port isn't even in use. I'm not throwing any errors with my current set up, I'm all dried up for ideas.
int main(){
int sock_fd;
int conn_fd;
struct sockaddr_in serv_addr;
struct sockaddr_in cli_addr;
socklen_t* serlen;
socklen_t* clilen;
clilen = malloc(sizeof(socklen_t));
serlen = malloc(sizeof(socklen_t));
*serlen = sizeof(serv_addr);
*clilen = sizeof(cli_addr);
/*=============================Create Socket=============================*/
//Create Socket
sock_fd = socket(AF_INET, SOCK_STREAM, 0);
if(sock_fd<0){
fprintf(stderr,"error creating socket\n");
exit(1);}
//Initialize Server Address Struct
bzero((char *) &serv_addr, *serlen);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = 0;
/*=============================Bind Address==============================*/
//Bind socket to an address
if(bind(sock_fd,(struct sockaddr*)&serv_addr,*serlen)<0){
fprintf(stderr,"error binding\n");
exit(1);}
//Get socket data
if(getsockname(sock_fd,(struct sockaddr*)&serv_addr, serlen)<0){
fprintf(stderr,"error with socket name");
exit(1);}
/*=============================Server Started============================*/
//Listen for connections
listen(sock_fd,32);
//Print port
printf("%i", serv_addr.sin_port);
conn_fd = accept(sock_fd,(struct sockaddr*)&cli_addr,clilen);
/**Do something exciting with my new connection**/
}
Are you really trying to listen on port zero? Try a high port number, preferably > 1024. /etc/services will give a hint about free ports - but it only a set of comments, those port numbers are not enforced.
Edit: another hint. The port number should be in network order, so the assignment should use htons(). It could be that the "random numbers" you are getting are simple numbers that appear garbled because you might be on a little-endian machine (like Intel). When you print them, convert them back using ntohs().
props to #askmish for inspiring this one
//Print port
printf("%i", serv_addr.sin_port);
becomes
//Print port
printf("%i", htons(serv_addr.sin_port));
In your code:
Instead of:
serv_addr.sin_port = 0;
try this:
serv_addr.sin_port=htons(2056);//Any port no.
Instead of:
listen(sock_fd,32);
try this:
if(listen(sock_fd,SOMAXCONN)<0)//Just to be sure that you are considering max. no. of requests
{ fprintf(stderr,"error with listen");
exit(1);}
Also for:
conn_fd = accept(sock_fd,(struct sockaddr*)&cli_addr,clilen);
Add this:
if(conn_fd <0)
{
//handle the error here
}
If none of these solve your issues, then, there might be problem with the client code or your server environment.
I'm trying to implement a basic UDP protocol wherein a Sender sends a UDP datagram to a Service, which then sends a response datagram back, using the source address and source port from the incoming datagram.
Normally you'd have the Sender also listen for the response on that port. But I want the response to be picked up by a separate program (the Listener) also running on that host. So:
On host A, Listener starts and binds to port 12345, and blocks on recvfrom.
On host A, Sender sends datagram to Service running on host B, setting the source address and port to host A, port 12345.
Service on host B sends a response to host A port 12345.
Response is picked up by Listener.
Setting the source address and port is done by binding to them. So I need both Sender and Listener to bind to the same port. Setting SO_REUSEADDR in both allows this. Note that I'm not using multicast here.
But the responses aren't reliably being picked up by Listener. There are two exceptions I've observed:
I find that if the Sender closes the socket immediately after sending the first datagram, then the response will get to the Listener.
Alternatively, if the Sender is started first and binds before the Listener, the responses will get picked up by the Listener.
I've been working from examples from the internet and haven't found documentation that clearly describes what should happen. But a few places I've seen have hinted that, for Unicast, only the most recent process to bind to the port will receive datagrams sent to it.
My question is, can I send UDP datagrams so that responses (sent using the source address and port) will be picked up by another process? If the above process can't be made to work, is there a way to set the source information on an outgoing datagram without binding to that port?
A few other points:
Each process should be started independently and be able to be restarted without interfering with the other. So I don't think I can have one open the socket and spawn the other.
I don't need to receive packets from both processes. One process only sends, and the other only receives.
Ideally, the solution would be portable enough to run on common Unixes and Windows.
Finally, if it's simply not possible then I'll fall back to using a single process to perform both functions. I'm not too stressed about it but I am interested in doing it if it is possible somehow. :-)
Networking code follows...
Sender code
void run(Options *options)
{
struct sockaddr_in si_me, si_other;
int s;
socklen_t slen = sizeof(si_other);
int reuse = 1;
struct hostent *he;
if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
die("socket");
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) != 0)
die("setsockopt");
// Bind to the "listen port", so that outgoing datagrams have the correct source information
memset((char *) &si_me, 0, sizeof(si_me));
si_me.sin_family = AF_INET;
si_me.sin_port = htons(options->listen_port);
si_me.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(s, (struct sockaddr *) &si_me, sizeof(si_me)) != 0)
die("bind");
memset((char *) &si_other, 0, sizeof(si_other));
si_other.sin_family = AF_INET;
si_other.sin_port = htons(options->service_port);
if (!(he = gethostbyname2(options->service_host, AF_INET)))
die("gethostbyname2");
memmove(&si_other.sin_addr.s_addr, he->h_addr, he->h_length);
while (1)
{
int len;
char *buf;
// Create outgoing message in buf
...
if (sendto(s, buf, len, 0, (struct sockaddr *) &si_other, slen) == -1)
die("sendto");
}
close(s);
}
Listener code
static void run(Options *options)
{
struct sockaddr_in si_me, si_other;
int s;
socklen_t slen = sizeof(si_other);
char buf[BUFLEN];
int reuse = 1;
if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
die("socket");
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) != 0)
die("setsockopt");
// Bind to the same "listen port" to pick up responses to datagrams sent by Sender
memset((char *) &si_me, 0, sizeof(si_me));
si_me.sin_family = AF_INET;
si_me.sin_port = htons(options->listen_port);
si_me.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(s, (struct sockaddr *) &si_me, sizeof(si_me)) == -1)
die("bind");
while (1)
{
int nr;
nr = recvfrom(s, buf, BUFLEN, 0, (struct sockaddr *) &si_other, &slen);
if (nr == -1)
die("recvfrom");
// Process the received message
...
}
close(s);
}
A related question is Using netcat to send a UDP packet without binding, where one answer seems to suggest it should be possible using SO_SOCKADDR, but did not quite explain how it would work in my case.
is there a way to set the source information on an outgoing datagram
without binding to that port?
There is no portable way. A solution for Linux, using IP_PKTINFO, is this answer to How to re bind a udp socket in Linux.
1: You can send from different port on B
A binds 12345 sends to B:12345
B:12345 - process 1 - recv
B:12346 - process 2 - send to A:12345
2: You can construct packet with fake back address with raw sockets
First solution is better
I'm trying to simulate a DHCP server as a university task. It's required to execute at least 2 servers (or more up to 255) since several clients will be sending messages to these servers using BROADCAST (that's where the limit of 'only' 255 servers comes from).
But when I'm trying to execute 2 servers in 2 different terminals in Ubuntu, the second server executed is rejected. I guess it's due to IP at the same localhost or whatever (I'm sorry but I don't know too much about communication protocols)
How can I run several servers on the same machine? Our teacher told us about using VMWare to run another Linux OS, and try to run both, but for me this solution is far away from my thoughts... I will post the server and client connection statements, although I don't know if there's a problem with the C statements, or the OS configuration, etc.
Server:
int sockfd, newsockfd, clilen, n;
struct sockaddr_in cli_addr, serv_addr ;
char host_name[200];
int size = sizeof(struct DHCP);
char buffer[size];
struct MACIP *macip;
if ((sockfd = socket(AF_INET, SOCK_DGRAM,0)) < 0) {
printf("server: can't open datagram socket\n");
return -1;
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(0);
serv_addr.sin_port = htons(SERV_UDP_PORT);
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) <0) {
printf("server: can't bind local address\n");
return -1;
}
Client:
int sockfd, n, clilen;
struct sockaddr_in serv_addr, cli_addr;
char serv_host_addr[30];
int size = sizeof(struct DHCP);
char buffer[size];
printf("Dirección IP del servidor (a.b.c.d) => ");
gets(serv_host_addr);
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("client: can't open datagram socket");
return -1;
}
int opt=1;
if (setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST,&opt, sizeof(opt))<0) {
perror("Error opcion socket");
close(sockfd);
return 1;
}
bzero((char *)&cli_addr,sizeof(cli_addr));
cli_addr.sin_family = AF_INET;
if (bind(sockfd, (struct sockaddr *) &cli_addr,sizeof(cli_addr)) < 0) {
perror("client: can't bind a port");
return -1;
}
serv_addr.sin_family = AF_INET;
inet_pton(AF_INET, serv_host_addr,&serv_addr.sin_addr);
//serv_addr.sin_addr.s_addr = inet_addr(serv_host_addr);
serv_addr.sin_port = htons(SERV_UDP_PORT);
Thank you very much in advance.
Every instance of your UDP server must listen on another port. Key line in your code is this:
serv_addr.sin_port = htons(SERV_UDP_PORT);
Looks like you have the port number as a constant (SERV_UDP_PORT). To make multiple servers run at the same time you need another port for each one.
Probably best solution in your case is to have a command line argument that would define the port on which you start your server.
Each client needs to know which port (and address of course) to connect to as well. So make your client to accept similar command line argument.
To run multiple servers, they should listen on different ports on same network interface. You may get away by using two network interfaces (say wifi and ethernet) on same network with different ips.
You might try to set up alias interfaces on an existing interface. Such alias interfaces then get their own ip address each.
Using the loopback interface (lo), which typical has 127.0.0.1 assigned, such aliases to this interface could then be called lo:0, lo:1 ... and would carry the ip addresses 127.0.0.2, 127.0.0.3, ....
For details on how to achieve this see man ifconfig.