LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 04-28-2009, 04:04 AM   #1
saikrishnan7
LQ Newbie
 
Registered: Apr 2009
Posts: 13

Rep: Reputation: 0
Creating multiple UDP sockets in a 'C' program


How do I create two UDP sockets in a single code? I want to to write a forwarder that is connected to a client and a server such that a message from the client to the server passes thro' the forwarder and vice-versa. I need two sockets one for connecting to the client and another for connecting to the server. Is there a better idea than creating two sockets?
 
Old 04-28-2009, 04:42 AM   #2
dmail
Member
 
Registered: Oct 2005
Posts: 970

Rep: Reputation: Disabled
Quote:
Originally Posted by saikrishnan7 View Post
Is there a better idea than creating two sockets?
Yes using one UDP socket, UDP is a connectionless protocol.
 
Old 04-28-2009, 06:33 AM   #3
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541

Rep: Reputation: 335Reputation: 335Reputation: 335Reputation: 335
Quote:
Originally Posted by dmail View Post
Yes using one UDP socket, UDP is a connectionless protocol.
But a connection can be setup if desired, for example when it is known that many messages will be sent between host A and host B.

When using sendto(), a "virtual" connection is set up and torn down each time a message is sent. This is inefficient if many messages need to be sent.

By performing a connect(), and then employing send(), the UDP socket will only be able to send messages to the chosen host as specified in the connect() call.

Back to what the OP was inquiring about, yes, one socket could be used. Whether one or two sockets are used, the app will still need to discern who is sending a message and thus who to forward the message to.

The bigger question is how does this "middle-man" app know where to forward messages to? Is the app to be initialized with hard-coded client host names or IP addresses? This information is needed when a sendto() is performed. If this does not make sense, take this scenario:

1. app runs
2. app receives message using recvfrom() -- ok, now app knows about one client
3. app forwards message using sendto() -- oops, app does not have forwarding information (host,port) of other client, at least not yet.

Maybe each client will register itself with the app, and thus the app will serve as a router?
 
Old 04-28-2009, 08:20 AM   #4
saikrishnan7
LQ Newbie
 
Registered: Apr 2009
Posts: 13

Original Poster
Rep: Reputation: 0
Quote:
Originally Posted by dwhitney67 View Post
But a connection can be setup if desired, for example when it is known that many messages will be sent between host A and host B.

When using sendto(), a "virtual" connection is set up and torn down each time a message is sent. This is inefficient if many messages need to be sent.

By performing a connect(), and then employing send(), the UDP socket will only be able to send messages to the chosen host as specified in the connect() call.

Back to what the OP was inquiring about, yes, one socket could be used. Whether one or two sockets are used, the app will still need to discern who is sending a message and thus who to forward the message to.

The bigger question is how does this "middle-man" app know where to forward messages to? Is the app to be initialized with hard-coded client host names or IP addresses? This information is needed when a sendto() is performed. If this does not make sense, take this scenario:

1. app runs
2. app receives message using recvfrom() -- ok, now app knows about one client
3. app forwards message using sendto() -- oops, app does not have forwarding information (host,port) of other client, at least not yet.

Maybe each client will register itself with the app, and thus the app will serve as a router?
Can I get the destination address as a user input so that the app can forward it? If I use the same socket how will I designate a port when I forward the message...Consider this scenario..A sends a message to app on port 5000 now how can I make B to connect to 5000 of app...won't I get a "port already in use" error? Since 5000 of app is listening to port 5000 of A.
 
Old 04-28-2009, 08:28 AM   #5
saikrishnan7
LQ Newbie
 
Registered: Apr 2009
Posts: 13

Original Poster
Rep: Reputation: 0
Can I get the destination address as a user input so that the app can forward it? If I use the same socket how will I designate a port when I forward the message...Consider this scenario..A sends a message to app on port 5000 now how can I make B to connect to 5000 of app...won't I get a "port already in use" error? Since 5000 of app is listening to port 5000 of A.
 
Old 04-28-2009, 09:51 AM   #6
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541

Rep: Reputation: 335Reputation: 335Reputation: 335Reputation: 335
For your hypothetical collection of systems, let's call them A, B, and M (for middle-man).

Server M should create a socket, and then bind a port to all/any address on the local host or to a specific address on that host (i.e. the IP assigned to eth0).

Obviously, if M binds a port, then if either A and/or B are running on the same system, then they will not be able to bind to the same address/port combo.

Without a doubt, A and B will need to be given the address and port used by M. How this is accomplished is up to you. Use command-line args or a configuration file, or some other means.

M on the other, does not necessarily need to know about A and B's address/port. You could always wait for both of these clients to register themselves; basically once they send a message to M, then M is aware of their respective address/port.

If you want to forgo the registration process, then M will need address/port info about A and B. As stated earlier, neither A nor B will be able to utilize the same port as M if they are running on the same host as M, and M has bound its port to all (INADDR_ANY) interfaces.

If A and/or B are assigned specific ports, then these ports should be bound on their respective systems.

Last edited by dwhitney67; 04-28-2009 at 09:53 AM.
 
Old 04-28-2009, 11:33 AM   #7
saikrishnan7
LQ Newbie
 
Registered: Apr 2009
Posts: 13

Original Poster
Rep: Reputation: 0
I have partially coded the middle-man(M) can you pls provide some suggestions on how to develop it. This must also support two-way traffic.

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>

int main()
{
int sock,sockfd;
int addr_len, bytes_read;
char recv_data[1024],send_data[1024];
struct sockaddr_in server_addr ,client_addr, new_addr;
/*new_addr stands for address of to be implemented B*/

if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
perror("Socket");
exit(1);
}
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
perror("Socket");
exit(1);
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(5000);
server_addr.sin_addr.s_addr = INADDR_ANY;
bzero(&(server_addr.sin_zero),sizeof(server_addr));


if (bind(sock,(struct sockaddr *)&server_addr,
sizeof(struct sockaddr)) == -1)
{
perror("Bind");
exit(1);
} /* middleman bound with A */
if (bind(sock,(struct sockaddr *)&server_addr,
sizeof(struct sockaddr)) == -1)
{
perror("Bind");
exit(1);
} /* middleman bound with B */

addr_len = sizeof(struct sockaddr);


while (1)
{
/* Message received from A by middle man */
bytes_read = recvfrom(sock,recv_data,1024,0,
(struct sockaddr *)&client_addr, &addr_len);
recv_data[bytes_read] = '\0';
/* Message sent to B by middleman after receiving from A */
sendto(sock, recv_data, strlen(recv_data), 0,
(struct sockaddr *)&new_addr, addr_len);
}

return 0;
}


Assuming that I use 3 different systems for this how do I specify to B about the port it needs to bind on, in order to get connected with the middleman. A is connected to M on port 5000, is it possible to connect B on 5000. when it receives the data.
 
Old 04-28-2009, 11:58 AM   #8
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541

Rep: Reputation: 335Reputation: 335Reputation: 335Reputation: 335
You are creating two sockets, but appear to be using only one of them. Also, you are binding the same socket twice; I does not make sense to do this, and since I have never tried it, I do not know what the result will be.

As dmail and I pointed out, a single socket will suffice. I rarely ever code the low-level socket library stuff anymore, thus I will provide you a high-level synopsis of what I would do for the M app:

(btw, note the code formatter... you should learn to use this too! Look for the # editor button when you post replies.)

Code:
SocketInfo sinfo = { AF_INET, SOCK_DGRAM, IPPROTO_UDP };

CreateSocket(&sinfo);

Bind(&sinfo, port, 0);   // bind to all addresses (i.e. INADDR_ANY)

for (;;)
{
  char           buf[1024] = {0};
  char*          srcAddr = 0;
  unsigned short srcPort = 0;
  int            bytesRcvd = RecvFrom(&sinfo, buf, sizeof(buf), &srcAddr, &srcPort);

  if (bytesRcvd > 0)
  {
    // determine if A sent the message, or if it was B;
    // this assumes you have the IP address (and port) of A and B.

    if (strcmp(srcAddr, addrA) == 0)
    {
       SendTo(&sinfo, buf, bytesRcvd, addrB, portB);
    }
    else if (strcmp(srcAddr, addrB) == 0)
    {
       SendTo(&sinfo, buf, bytesRcvd, addrA, portA);
    }
    else
    {
       // received msg from unknown source
    }
  }
}
The 'sinfo' is a struct:
Code:
typedef struct
{
  int  m_Domain;
  int  m_Type;
  int  m_Protocol;
  char m_SocketName[108];

  int  m_Socket;     // store the socket descriptor here
} SocketInfo;
P.S. I'm more of a C++ developer than C, so forgive me if the code above does not make sense or employs questionable practices.
 
Old 04-28-2009, 02:36 PM   #9
saikrishnan7
LQ Newbie
 
Registered: Apr 2009
Posts: 13

Original Poster
Rep: Reputation: 0
You are really helping me a lot. Thanks. I am quite new to all this so my questions could be trivial at times. Please pardon me for that. In your reply you have asked me to store the socket descriptor in the variable m_Socket inside the structure? I don't understand what I need to store here? Usually socket descriptors are the first arguments for sendto() and recvfrom() and u have used &sinfo. I am slightly confused. So can u brief me on this?
 
Old 04-28-2009, 08:46 PM   #10
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541

Rep: Reputation: 335Reputation: 335Reputation: 335Reputation: 335
No, no... the structure is not needed. That was just me using a handy way to keep all information about the socket in one place.

Typically a developer would write the code similar to yours... a 100+ lines of code just to set the socket up. I prefer to modularize everything with functions. With socket programming, one seems to have to pass the same args over and over again to various functions. Thus I came up with the structure to hold everything I would possibly need.

If you ever develop a socket library, to handle not only UDP, but TCP, and for that matter, raw sockets, then you will understand this.

Anyhow, for each of the functions I noted in the previous example I posted, you will need to write the code that performs the action. You can string along this code, as I said into 100+ lines of contiguous code, or write your own functions.

If you prefer, you can use my socket library, which I have spent more time developing for C++ apps rather than C.
 
Old 04-28-2009, 09:02 PM   #11
saikrishnan7
LQ Newbie
 
Registered: Apr 2009
Posts: 13

Original Poster
Rep: Reputation: 0
URGENT!! Very Basic Socket Programming- PLease please help sooon!!!

Dear all,
I have a very basic doubt in socket programming... I want to do a basic UDP Client Server program... I want to know how the program takes the input... How does the program know the server and the client addresses? Do we give them in the commmand line? If so, which is the part in the program that recognizes input from the command line? Please reply sooon...



If anyone has a code, please please forward them to me now...


Thanks in advance,
Sai
 
Old 04-29-2009, 03:38 AM   #12
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541

Rep: Reputation: 335Reputation: 335Reputation: 335Reputation: 335
Generally a server is not told about the addresses of the clients; it finds out these addresses when the client connects (say when using TCP), or when the client sends a message (when using UDP).

The client, on the other hand, must be told the address of the server, or just assume the address is 127.0.0.1. The client must also be made aware of the port number the server is using.

If you want to pass along this information to the client using the command line, say like:
Code:
myclient -p 10000 -h 192.168.1.105
where -p is used to state the port number, and -h the address of the server, then define your main() function as:
Code:
int main(int argc, char** argv)
{
  ...
}
The command line args will be available in argv[1], argv[2], etc. argv[0] is always the program name.

You can use getopt(), if you wish, to parse the command line args. Please read the man-page for this library function for details.

With respect to your code, you will need to put in some effort yourself to develop it. This forum is not about doing the work for others, but for helping others with their work (when there is a problem).

I think you ought to spend some time learning the C programming language in more detail before attempting to conquer socket programming. Passing/processing command line arguments is one of the basic features of pretty much every programming language.

Last edited by dwhitney67; 04-29-2009 at 03:40 AM.
 
Old 04-30-2009, 07:12 AM   #13
saikrishnan7
LQ Newbie
 
Registered: Apr 2009
Posts: 13

Original Poster
Rep: Reputation: 0
Video over Sockets

Hello Whitney,
I have developed a code for a forwarder. It does the following :

1) The forwarder acts as a server connected to 2 clients. It must receive from one client and forward it to the other.

2) Client 1 connects.

3) Client 2 connects.

4) Client 1 sends a file. I used file open to read from file, and then the file is forwarded to the other client by the forwarder. The file gets dumped into the other client.


I have done this (Sent a text file). Now, I want to be able to send video files using this code. Can I just read them the same way as text files?

If so, how does the receiving client receive the video, and maybe play it?

Also, I want to do the following, but I don't know how to make my above code work for this:

Real Server -------> Forwarder ------------> Forwarder -----> Real Client


I want to send videos. And it should be 2 way communication. I don't understand what a "REAL SERVER" or a "REAL CLIENT" is. Kindly also tell me if the code I made for the other one fits into this, and what changes I have to make for the real server application.
 
Old 04-30-2009, 07:18 AM   #14
saikrishnan7
LQ Newbie
 
Registered: Apr 2009
Posts: 13

Original Poster
Rep: Reputation: 0
Video Over Sockets code

This is the code for the forwarder I made :

CLIENT ( The one that sends the file to the other client thro' forwarder) :-

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>


int main(int argc, char **argv)
{
int sock,a,addrlen,i=0;
struct sockaddr_in server_addr,client_addr;
struct hostent *host;
char send_data[1024] = "Hello!";
char recv_data[1024],ca[1024];

if (argc < 2)
{
printf("Not enough arguments\n"); return 0;
}

addrlen = sizeof(server_addr);

host= (struct hostent *) gethostbyname((char *)argv[1]);

if ((sock = socket(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK, 0)) == -1)
{
perror("Socket Creation Error");
exit(1);
}

server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(5000);
server_addr.sin_addr = *((struct in_addr *)host->h_addr);
bzero(&(server_addr.sin_zero),sizeof(server_addr));

printf("\nType Something (q or Q to quit):");
//gets(send_data);

// if ((strcmp(send_data , "q") == 0) || strcmp(send_data , "Q") == 0)
// break;
// else
struct stat statbuf;

FILE *file = fopen("ttt.c", "r");
while (1)
{
if (fgets(send_data, 1023, file) == NULL)
break;
sendto(sock, send_data, strlen(send_data)+1, 0, (struct sockaddr *)&server_addr, addrlen);
a = recvfrom(sock,recv_data,1024,0,(struct sockaddr *)&server_addr, &addrlen);
if (a == -1){continue; }
recv_data[a] = '\0';
printf("%s",recv_data);
fflush(stdout);
}
}


BELOW is the FORWARDER (that actually forwards the file to the other client) :-
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>

int main(int argc,char **argv)
{
int sock, bytes_read,addrlen,i=0;
char recv_data[1024],send_data[1024],ca[1024];
struct sockaddr_in server_addr , client_addr;
int clients[2] = {0,0};
struct sockaddr_in clientsAddr[2];
int yes = 1;

if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
{
perror("Socket Creation Error");
exit(1);
}

addrlen= sizeof(client_addr);

server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(5000);
server_addr.sin_addr.s_addr = INADDR_ANY;
bzero(&(server_addr.sin_zero),sizeof(server_addr));

if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&yes, sizeof(int)) < 0)
{
perror("Reuse option\n");
close(sock);
exit(1);
}

if (bind(sock,(struct sockaddr *)&server_addr,sizeof(struct sockaddr)) == -1)
{
perror("Bind Error");
close(sock);
exit(1);
}

printf("\n UDP Server waiting for client on port 5000 \n");
fflush(stdout);
while (1)
{
int sender = -1;
int receiver = -1;
printf("I : %d\n", i);
printf("Before recv\n");
bytes_read = recvfrom(sock,ca,1024,0,(struct sockaddr *)&client_addr, &addrlen);
printf("Received from Client port : %d\nString : %s\n", client_addr.sin_port, ca);
if(i < 2)
{
if ((clientsAddr[0].sin_addr.s_addr == client_addr.sin_addr.s_addr && clientsAddr[0].sin_port == client_addr.sin_port) ||
(clientsAddr[1].sin_addr.s_addr == client_addr.sin_addr.s_addr && clientsAddr[1].sin_port == client_addr.sin_port))
{
continue;
}
else
{
if (clients[0] == 0){ clients[0] = 1; memcpy(&clientsAddr[0], &client_addr, sizeof(client_addr)); i++;}
else if (clients[1] == 0){ clients[1] = 1; memcpy(&clientsAddr[1], &client_addr, sizeof(client_addr)); i++;}
printf("Client Connected\n");
}
}
if ((clientsAddr[0].sin_addr.s_addr == client_addr.sin_addr.s_addr && clientsAddr[0].sin_port == client_addr.sin_port))
sender = 0;
else
sender = 1;
receiver = (sender == 0) ? 1 : 0;
printf("Sender : %d __ Receiver : %d\n", sender, receiver);
if (i == 2 && sender >= 0 && receiver >= 0) // 2 clients connected
{
if ((strcmp(ca , "q") == 0) || strcmp(ca , "Q") == 0)
break;
else
printf("Received : %s\n",ca);
sendto(sock, ca, strlen(ca)+1, 0, (struct sockaddr *)&clientsAddr[receiver], addrlen);
sender = -1; receiver = -1;
}
}
return 0;
}
 
Old 04-30-2009, 10:03 AM   #15
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541

Rep: Reputation: 335Reputation: 335Reputation: 335Reputation: 335
Quote:
Originally Posted by saikrishnan7 View Post
...
1) The forwarder acts as a server connected to 2 clients. It must receive from one client and forward it to the other.
I do not understand this statement; how can the server connect to clients that have yet to establish a relationship? Furthermore, why would a server connect to the client(s)?

Quote:
Originally Posted by saikrishnan7 View Post
2) Client 1 connects.

3) Client 2 connects.
I presume you mean using the connect() call. This operation is not typical for UDP sockets, but it is permitted.

Quote:
Originally Posted by saikrishnan7 View Post
4) Client 1 sends a file. I used file open to read from file, and then the file is forwarded to the other client by the forwarder. The file gets dumped into the other client.
This sounds ok. But a question... you never explained the purpose of having the middle-man server; is it because the two clients cannot reach each other directly?

Quote:
Originally Posted by saikrishnan7 View Post
I have done this (Sent a text file). Now, I want to be able to send video files using this code. Can I just read them the same way as text files?
Text files are typically read using fgets(). Binary (video) files are read using fread(). A text file can also be read using fread(). Thus in an effort to keep your code simple, I would recommend that you always use fread().

Quote:
Originally Posted by saikrishnan7 View Post
If so, how does the receiving client receive the video, and maybe play it?
The receiving part is easy; just use a recv(). Playing the streaming video as soon as it is received is dependent upon the application that can perform this task. I am not that familiar with any video applications to provide you a worthwhile comment on how to approach this solution.

Quote:
Originally Posted by saikrishnan7 View Post
Also, I want to do the following, but I don't know how to make my above code work for this:

Real Server -------> Forwarder ------------> Forwarder -----> Real Client


I want to send videos. And it should be 2 way communication. I don't understand what a "REAL SERVER" or a "REAL CLIENT" is. Kindly also tell me if the code I made for the other one fits into this, and what changes I have to make for the real server application.
I still need clarification as to why you require the forwarder(s). Either way, communication between client and server, forwarder(s) in place or not, is the same. Generally the client is aware of the IP address and port number that the server is listening on. As for UDP sockets, they are bidirectional.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
client/server echo program of UDP sockets memisbah Programming 2 04-08-2008 10:27 AM
Need help with UDP sockets in c++ Shautieh Programming 5 02-20-2008 02:20 PM
Program to forward tcp sockets to unix domain sockets mikepol Linux - Networking 0 09-27-2007 09:49 AM
Sending files over udp sockets in C raszagal Programming 9 11-27-2004 11:49 AM
sockets, UDP, using select() Pres Programming 3 08-22-2003 09:41 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 05:54 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration