I have a client which is subscribed to several multicast feeds via a third party library with a callback. The third party library does something like this:
sockaddr_in senderAddr;
socklen_t len = sizeof(struct sockaddr_in);
for fd in allMulticastFeeds:
{
recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr*)&senderAddr, &len);
(*func)(buf, rc, &senderAddr, 0, stuff*);
}
Several listeners subscribe to me, and my job is to parse the messages contained in buf and callback on the appropiate clients subscribed to me. One of the options clients who subscribe to me give me is whether they want to receive messages outgoing from the local host or not. Because different subscribers to me might want different behavior I simply cannot translate this to a disabling of multicast and I must, for each client, check whether he or she requested local messages, and if not, then hand them over only if I can verify from the sockaddr_in that they are not local.
My approach to do this was to do the following in the constructor of my service:
sockaddr_in self;
hostent *he;
char local[HOST_NAME_MAX];
gethostname(local, sizeof(local));
he = gethostbyname(local);
if (he)
{
memcpy(&self.sin_addr, he->h_addr_list[0], he->h_length);
selfAddr_ = self.sin_addr.s_addr;
}
where selfAddr_ is a member variable of type long. Then, when I get the callback described above from the network listener I do something like this:
//code to get the correct listener for this type of packet after parsing it
if (listener->AskedForLocal || selfAddr_ != s_addr)
listener->onFoo(bla,bla);
where s_addr is the sin_addr.s_addr contained in the sockaddr_in* I get from the third party library calling recvfrom. This seemed to work when I tested it but I have a feeling it is failing sometimes and it might have to do with the adhoc using of the first element of he->h_addr_list. Is this method unreliable and if so, is the only reliable method to check every element of the he->h_addr_list against the incoming s_addr?
Looking at the constructor for your service and trying it on Ubuntu 10.04 LTS running as a virtualbox image I get selfAddr_ = 0x10107f
This corresponds to the loopback address 127.0.0.1
This might not be what you're looking for - I suspect you're probably after a specific network interface's IP address, if so try this answer.
Hope this helps.
Sorry but somehow I don't see 0x10107f corresponding to 127.0.0.1... Shouldn't that be 0x0100007F...
Related
So I wanted to make sure I am not missing something and I have the concepts clean in my head.
This is the part of the code I have:
UDP_Msg mensajeRecibidoUdp;
struct sockaddr_in c_ain;
sock_udp=socket(AF_INET,SOCK_DGRAM,0);
struct sockaddr_in c_ain;
socklen_t tam_dir;
while(1)
{
if(recvfrom(sock_udp, &mensajeRecibidoUdp, sizeof(UDP_Msg), 0,
(struct sockaddr*) &c_ain, &tam_dir) <0)
....
The problem is that it waits for a message to arrive. And the message is sent, but this code does not get anything, it doesn't unfreeze.
It's a simple exercise, and the client is already built. It gets the port from a file, then sends a UDP_Message that is a struct with a couple ints and an array (the client already knows the IP and port).
I thought the way I handle the buffer could be wrong, but every example I've seen uses it like that. I also thought that the c_ain variable might needed to be initialized, but that's not the case if I understand it properly. So I don't get why the process gets... blocked, not sure what's the proper word, and since a lot of time passes by, an alarm goes off and the process gets killed (because it should have got info and keep with the code but it did not).
I can add lots of other info, I tried to keep it short. I kind of know that call is the one that isn't working properly because of how it behaves when I run the client-server thingy.
Edit: Bind:
bzero((char*)&dir_udp_serv,sizeof(struct sockaddr_in));
dir_udp_serv.sin_family=AF_INET;
dir_udp_serv.sin_addr.s_addr=inet_addr(HOST_SERVIDOR);
dir_udp_serv.sin_port=0;
fprintf(stderr,"SERVIDOR: Asignacion del puerto servidor: ");
if(bind(sock_udp,
(struct sockaddr*)&dir_udp_serv,
sizeof(struct sockaddr_in))<0)
{
fprintf(stderr,"ERROR\n");
close(sock_udp); exit(1);
}
Second edit: I just realized I have two binds in the code. The idea is I create two connections on the same server, one for UDP and one for TCP. So I made the same steps for both UDP and TCP. From the answer I got I realize that might be wrong. Would it be only 1 bind per socket, even if I create two sockets, one for UDp and one for TCP?
The above does not seem to be the case.
Also, I don't know what more details should I add, but the server and client are both on the same computer so their address are both 127.0.0.1, but that's expected and I believe does not change anything as to why the server does not get the info sent from the client.
Ask yourself: on which port do your clients send their messages? Where is that port in your server code? Nowhere. You forgot to bind your local socket to your local address (and port) :
struct sockaddr_in local;
local.sin_family = AF_INET;
local.sin_addr.s_addr = inet_addr("0.0.0.0");
local.sin_port = htons(PORT); // Now the server will listen on PORT.
if(bind(sock_udp, (struct sockaddr*)&local, sizeof(local)) < 0){
perror("bind");
exit(1);
}
// Now you may call recvfrom on your socket : your server is truly listening.
Note that you only need to bind once. No need to put this in a loop.
Allright not sure if this is the place, but the answer to my own question was one expected: The server was listening in a port, and the client was sending to a different one. That was because of the way the port assigned was sent to the client: in my case, without transform it to network format (ntohs()), so when the client did htons(), the number was a completly different one.
I'm getting ready to attempt my first project involving networked communications. This is just a tinker-toy app with the purpose of self-teaching - nothing mission-critical here. I will need two nodes to communicate with each other. One will be an Android platform, so I will be using Java. The other node will be a RaspberryPi running Debian Linux. While I COULD use Java on this end as well and maybe just use RPC, what I would LIKE to do is develop my own little implementation-agnostic TCP/IP "protocol" for the two to communicate, and let the each implement it however works best. What I mean by "protocol" is I want a standard set of messages to be passed back and forth, along with some values with each. E.g.:
"Protocol" Definition:
MESSAGE TYPE A (Float arg, Int arg)
MESSAGE TYPE B (Int arg)
MESSAGE TYPE C (Int arg, String arg, Int arg)
An example "conversation":
Node 1 Node 2
A(5.4, 4) --->
B(6) --->
<---- C(3, 'Hello', 0xFF)
B(5) --->
<---- A(43.0, 16)
So my questions are:
(1) Does the above even make sense? Do I need to clarify my intent? Provide more info? This is my first forray into networked communication between two running programs, so I may be way off-base in what I'm asking for. If I'm approaching this the wrong way, I'd be happy for better recommendations.
(2) How would I go about this? Do I just stuff one long string into a TCP packet? Is there a better way?
Thanks!
You only need to fill a buffer with the data you want and then learn how to open and send data through a TCP socket. The kernel will handle how to arrange the payload and how to control the TCP stream. On the server end, you must learn how to listen on a TCP socket and read incoming data.
Socket Programming is the word you should be searching for.
I am working on a network programming using epoll. I have a connection list and put every client in the list. I can detect user disconnection by reading 0 if the user disconnected normally. However, if the user somehow got disconnected unexpectedly then there is no way it knows about this until it tries send data to the user.
I don't think epoll provides a nice way to handle this..so I think I should handle this on my own. I will be very appreciated if you guys can provide me anything like examples or references related to this problem.
epoll_wait will return a EPOLLHUP or EPOLLERR for the socket if the other side disconnects. EPOLLHUP and EPOLLERR are set automatically but you can also set the newer EPOLLRDHUP which explicitly reports peer shutdown.
Also if you use send with the flag MSG_NOSIGNAL it will set EPIPE on closed connections.
int resp = send ( sock, buf, buflen, MSG_NOSIGNAL );
if ( resp == -1 && errno == EPIPE ) { /* other side gone away */ }
Much nicer than getting a signal.
How about TCP Keepalives: http://tldp.org/HOWTO/TCP-Keepalive-HOWTO/overview.html. See "Checking for dead peers". A later section on the same site has example code: http://tldp.org/HOWTO/TCP-Keepalive-HOWTO/programming.html.
I have a web service that is running on IIS (6 or 7, doesn't matter) and I would like to know the port that the caller has sent their request/invocation from.
So if a client makes a call on my web service, how do I find out from the server side what the port number is they made the call from?
Is that something that even gets passed at even the lowest level? Just to be clear I'm not looking for the port for callback purposes. It's for logging only.
You should be able to find it as "REMOTE_PORT" in the server variables of the Server object.
However, this port should pretty much always be random, and is only active for the Request/Response pair the client is making. It should be can't be used for asynchronous call backs. Even your webservice when calling to someother service will use a random port number to initiate the request from. The only static port in the communication is the receiving port at the server end of the TCP connection.
If you service is on WCF, then:
OperationContext context = OperationContext.Current;
MessageProperties messageProperties = context.IncomingMessageProperties;
var endpointProperty = messageProperties[RemoteEndpointMessageProperty.Name]
as RemoteEndpointMessageProperty;
if (endpointProperty != null)
{
string sRemoteAddress = endpointProperty.Address;
int nRemotePort = endpointProperty.Port;
}
TCP sockets do have the concept of sender port number but it doesn't have much use in application level protocols. That said, considering the last paragraph of the OP, I think you're looking for some way to call back the client. The ports I said previously cannot be used for that. Asynchronous requests are identical to synchronous ones running on a separate thread, nothing special about them.
Some Network Address Translation-type devices will hide the actual "sending" port number from you. You would then have access to a useless IP address and a useless port number.
I'm implementing a simple service using datagrams over unix local sockets (AF_UNIX address family, i.e. not UDP). The server is bound to a public address, and it receives requests just fine. Unfortunately, when it comes to answering back, sendto fails unless the client is bound too. (the common error is Transport endpoint is not connected).
Binding to some random name (filesystem-based or abstract) works. But I'd like to avoid that: who am I to guarantee the names I picked won't collide?
The unix sockets' stream mode documentation tell us that an abstract name will be assigned to them at connect time if they don't have one already. Is such a feature available for datagram oriented sockets?
The unix(7) man page I referenced had this information about autobind UNIX sockets:
If a bind(2) call specifies addrlen as sizeof(sa_family_t), or the SO_PASSCRED socket option was specified for a socket that was not explicitly bound to an address, then the socket is autobound to an abstract address.
This is why the Linux kernel checks the address length is equal to sizeof(short) because sa_family_t is a short. The other unix(7) man page referenced by Rob's great answer says that client sockets are always autobound on connect, but because SOCK_DGRAM sockets are connectionless (despite calling connect on them) I believe this only applies to SOCK_STREAM sockets.
Also note that when supplying your own abstract namespace socket names, the socket's address in this namespace is given by the additional bytes in sun_path that are covered by the specified length of the address structure.
struct sockaddr_un me;
const char name[] = "\0myabstractsocket";
me.sun_family = AF_UNIX;
// size-1 because abstract socket names are not null terminated
memcpy(me.sun_path, name, sizeof(name) - 1);
int result = bind(fd, (void*)&me, sizeof(me.sun_family) + sizeof(name) - 1);
sendto() should likewise limit the address length, and not pass sizeof(sockaddr_un).
I assume that you are running Linux; I don't know if this advice applies to SunOS or any UNIX.
First, the answer: after the socket() and before the connect() or first sendto(), try adding this code:
struct sockaddr_un me;
me.sun_family = AF_UNIX;
int result = bind(fd, (void*)&me, sizeof(short));
Now, the explanation: the the unix(7) man page says this:
When a socket is connected and it
doesn’t already have a local address a
unique address in the abstract
namespace will be generated
automatically.
Sadly, the man page lies.
Examining the Linux source code, we see that unix_dgram_connect() only calls unix_autobind() if SOCK_PASSCRED is set in the socket flags. Since I don't know what SOCK_PASSCRED is, and it is now 1:00AM, I need to look for another solution.
Examining unix_bind, I notice that unix_bind calls unix_autobind if the passed-in size is equal to "sizeof(short)". Thus, the solution above.
Good luck, and good morning.
Rob
A bit of a late response, but for whomever finds this using google as I did. Rob Adam's answer helped me get the 'real' answer to this: simply use set (level SO_SOCKET, see man 7 unix) to set SO_PASSCRED to 1. No need for a silly bind.
I used this in PHP, but it doesn't have SO_PASSCRED defined (stupid PHP). It does still work, though, if you define it yourself. On my computer it has the value of 16, and I reckon that it will work quite portably.
I'm not so sure I understand your question completely, but here is a datagram implementation of an echo server I just wrote. You can see the server is responding to the client on the same IP/PORT it was sent from.
Here's the code
First, the server (listener)
from socket import *
import time
class Listener:
def __init__(self, port):
self.port = port
self.buffer = 102400
def listen(self):
sock = socket(AF_INET, SOCK_DGRAM)
sock.bind(('', self.port))
while 1:
data, addr = sock.recvfrom(self.buffer)
print "Received: " + data
print "sending to %s" % addr[0]
print "sending data %s" % data
time.sleep(0.25)
#print addr # will tell you what IP address the request came from and port
sock.sendto(data, (addr[0], addr[1]))
print "sent"
sock.close()
if __name__ == "__main__":
l = Listener(1975)
l.listen()
And now, the Client (sender) which receives the response from the Listener
from socket import *
from time import sleep
class Sender:
def __init__(self, server):
self.port = 1975
self.server = server
self.buffer = 102400
def sendPacket(self, packet):
sock = socket(AF_INET, SOCK_DGRAM)
sock.settimeout(10.75)
sock.sendto(packet, (self.server, int(self.port)))
while 1:
print "waiting for response"
data, addr = sock.recvfrom(self.buffer)
sock.close()
return data
if __name__ == "__main__":
s = Sender("127.0.0.1")
response = s.sendPacket("Hello, world!")
print response