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 |
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
Are you new to LinuxQuestions.org? Visit the following links:
Site Howto |
Site FAQ |
Sitemap |
Register Now
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
|
|
|
04-28-2009, 04:04 AM
|
#1
|
LQ Newbie
Registered: Apr 2009
Posts: 13
Rep:
|
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?
|
|
|
04-28-2009, 04:42 AM
|
#2
|
Member
Registered: Oct 2005
Posts: 970
Rep:
|
Quote:
Originally Posted by saikrishnan7
Is there a better idea than creating two sockets?
|
Yes using one UDP socket, UDP is a connectionless protocol.
|
|
|
04-28-2009, 06:33 AM
|
#3
|
Senior Member
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541
|
Quote:
Originally Posted by dmail
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?
|
|
|
04-28-2009, 08:20 AM
|
#4
|
LQ Newbie
Registered: Apr 2009
Posts: 13
Original Poster
Rep:
|
Quote:
Originally Posted by dwhitney67
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.
|
|
|
04-28-2009, 08:28 AM
|
#5
|
LQ Newbie
Registered: Apr 2009
Posts: 13
Original Poster
Rep:
|
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.
|
|
|
04-28-2009, 09:51 AM
|
#6
|
Senior Member
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541
|
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.
|
|
|
04-28-2009, 11:33 AM
|
#7
|
LQ Newbie
Registered: Apr 2009
Posts: 13
Original Poster
Rep:
|
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.
|
|
|
04-28-2009, 11:58 AM
|
#8
|
Senior Member
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541
|
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.
|
|
|
04-28-2009, 02:36 PM
|
#9
|
LQ Newbie
Registered: Apr 2009
Posts: 13
Original Poster
Rep:
|
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?
|
|
|
04-28-2009, 08:46 PM
|
#10
|
Senior Member
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541
|
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.
|
|
|
04-28-2009, 09:02 PM
|
#11
|
LQ Newbie
Registered: Apr 2009
Posts: 13
Original Poster
Rep:
|
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
|
|
|
04-29-2009, 03:38 AM
|
#12
|
Senior Member
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541
|
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.
|
|
|
04-30-2009, 07:12 AM
|
#13
|
LQ Newbie
Registered: Apr 2009
Posts: 13
Original Poster
Rep:
|
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.
|
|
|
04-30-2009, 07:18 AM
|
#14
|
LQ Newbie
Registered: Apr 2009
Posts: 13
Original Poster
Rep:
|
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;
}
|
|
|
04-30-2009, 10:03 AM
|
#15
|
Senior Member
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541
|
Quote:
Originally Posted by saikrishnan7
...
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
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
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
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
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
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.
|
|
|
All times are GMT -5. The time now is 05:54 PM.
|
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.
|
Latest Threads
LQ News
|
|