I'm currently working with a Laser Sensor that delivers a UDP data stream on Port 2368. I can see the packets with Wireshark.
As I'm not able to post an image, I write what Wireshark shows for a packet:
Source: 192.168.17.141
Destination: 192.168.3.255
Protocol: UDP
Source Port: https (443)
Destination Port: opentable (2368)
However, I want to read the packets using sockets with following example C program:
int main(int argc, char *argv[])
{
int sock, n, res;
unsigned int length = 1206;
char* buffer = new char[1206];
sock= socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0) error("socket");
uint16_t udp_port = 2368;
sockaddr_in my_addr;
socklen_t len = sizeof(sockaddr_in);
memset(&my_addr, 0, sizeof(my_addr));
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(udp_port);
my_addr.sin_addr.s_addr = INADDR_ANY;
cout << my_addr.sin_family << endl;
cout << my_addr.sin_port << endl;
cout << my_addr.sin_addr.s_addr << endl;
res = bind(sock, (sockaddr *)&my_addr, sizeof(sockaddr_in));
if (res == -1)
{
perror("bind");
return -1;
}
while (true)
{
n = recvfrom(sock,buffer,1,0,NULL,NULL);
if (n < 0) error("recvfrom");
}
close(sock);
return 0;
}
The program is successful until it comes to recvfrom(). There the socket waits for packages and does not receive anything. I wrote the same program for Windows with Winsock and it worked perfectly. As I am relatively new to Linux OS I do not know how to fix this problem and would be thankful for advice!
Additional information: I manually assigned following IP and netmask to eth4 (this is the interface where the device is connected):
IP: 192.168.3.5
NM: 255.255.255.0
Set the SO_BROADCAST option, even for receiving. According to the socket(7) manpage:
SO_BROADCAST:
Set or get the broadcast flag. When enabled, datagram sockets receive packets sent to a broadcast address and they are allowed to send packets to a broadcast address. This option has no effect on stream-oriented sockets.
It could also be that your interface config is incorrect. Verify that you have a 192.168.3.xxx/24 address configured for the interface in question.
char buffer[1200+6]; /* no need for dynamic buffers */
...
n = recvfrom(sock, buffer, sizeof buffer, 0, NULL, NULL);
BTW your usage of recvfrom() is equivalent to
n = recv(sock, buffer, sizeof buffer, 0);
, or even:
n = read(sock, buffer, sizeof buffer);
You have
IP: 192.168.3.5 NM: 255.255.255.0
and
Source: 192.168.17.141 Destination: 192.168.3.255
This can't work, if there is no router involved. Try
IP: 192.168.3.5 NM: 255.255.0.0
as an interims measure, but do read up on IP
Edit: Maybe better look into your Laser sensor and set it to 192.168.3.[something free] with Destination directly your 192.168.3.5, and debug the broadcasting later.
Related
new to multicast networking, I need to receive UDP packets from a multicast channel through one of the NICs on my windows box, followed Microsoft docs and some blog entry, but still having issues.
I create a socket via
ls = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
call.
Then setsockopt to SO_REUSEADDR
unsigned int reuse = 1;
if( setsockopt(ls, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse, sizeof(reuse)) < 0 )
{
LOG4CXX_ERROR(logger, "Reusing ADDR failed. Err: " << WSAGetLastError());
}
If socket is good
int result = bind(ls, reinterpret_cast<SOCKADDR*>(&server), sizeof(server));
where
server.sin_family = AF_INET;
server.sin_addr.s_addr = htonl(INADDR_ANY);
server.sin_port = htons(myport);
If bind succedes
struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr = inet_addr("e.f.g.h");
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
if( setsockopt(ls, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char*)&mreq, sizeof(mreq)) < 0 )
{
LOG4CXX_ERROR(logger, "setsockopt multicast group add membership failed. Err: " << WSAGetLastError());
}
The box on which I need to receive packets has four NICs, network administrators told me that I have to use the third one, let's say that it has a.b.c.d IPv4 address
They told me also that mcast IP is e.f.g.h
If I run windump.exe -i 3 on my windows box I see something like this
... 12:53:58.454987 IP i.k.l.m.xxxxx > e.f.g.h.myport: UDP, length 58
...
After initializing my UDP socket I call recvfrom
sz = recvfrom(ls, buffer, DATA_BLOCK_SIZE, 0, reinterpret_cast<SOCKADDR*>(&client), &size);
where sz is an int, ls is my socket, buffer is a "suitable buffer", DATA_BLOCK_SIZE is buffer size, client is a SOCKADDR pointer to receive info from the sender, and size is the received message size.
My code stucks in the recvfrom call never receiving anything.
I'm clearly making a mistake somewhere but not understanding where and worse why.
If someone can explain me what's happening it will be very appreciated.
SOLVED ...
I changed these lines only
struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr = inet_addr("e.f.g.h");
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
to
struct ip_mreq mreq;
inet_pton(AF_INET, "e.f.g.h", &(mreq.imr_multiaddr));
inet_pton(AF_INET, "a.b.c.d", &(mreq.imr_interface));
As I have guessed I was not correctly indicating in my struct ip_mreq which was the network interface to use for multicast messages.
It was my fault. Sorry for the noise.
I capture all the packets in one side with help of nfqueue, "record" them (all the data: ip info, next protocol info etc) with nfq_get_payload and deliver them into another side with help of udp. How can I restore this packet on another side and then send to myself(2 side) like there is no udp-encapsulation between? Should I use some nfqueue API or I have to implement all the protocols packet creation (UDP, ICMP, TCP, etc)? And how should I send this restored packet?
Ok, I successfully recreated and sent forward my packet encapsulated in UDP. After recreation I needed to send this packet to another IP, but you can use original destination address. So the code snippet:
char *full_packet;
int size;
// some actions to get full_packet and size from UDP packet
// assume you recreated this: int size = nfq_get_payload(nfa, &full_packet);
int sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
// also optional string needed in my case:
setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, "wlan0", strlen("wlan0"));
if (sock == -1) {
perror("socket() failed");
return 1;
}
struct sockaddr_in to;
struct ip *iph = (struct ip *)full_packet;
to.sin_addr.s_addr = inet_addr("192.168.0.107"); // here you can set IP address where you need send this packet
to.sin_family = AF_INET;
int bytes = sendto(sock, full_packet, size, 0, (struct sockaddr*) &to, sizeof(to));
if (bytes == -1) {
perror("send() failed");
return 1;
}
I hope this will help somebody
I have the following configuration for my experiment.
Wifi(Belkin) router connected to Internet.
Laptop with Windows 7 OS
Laptop with Ubuntu OS.
Experiment: When I connect both of my laptop to Wifi router it assigns DHCP IPs 192.168.2.2 to Linux & 192.168.2.3 to Win 7. Both of them can browse internet.
I start a UDP server on my Linux machine with the following code.
int main(int argc, char *argv[]) {
int sd, rc, n, cliLen, flags;
struct sockaddr_in cliAddr, servAddr;
char msg[MAX_MSG];
//Create a socket
sd=socket(AF_INET, SOCK_DGRAM, 0);
if(sd<0){ printf("%s: cannot open socket \n",argv[0]); exit(1); }
//Bind now to a port
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = inet_addr("192.168.2.2");
servAddr.sin_port = htons(9999);
rc = bind (sd, (struct sockaddr *) &servAddr,sizeof(servAddr));
if(rc<0) {printf("%s: cannot bind port number %d \n", argv[0], 9999);exit(1);}
//We are done ... Notify User
printf("%s: waiting for data on port UDP %u\n",argv[0],LOCAL_SERVER_PORT);
//Server's Infinite Loop
while(1)
{
memset(msg,0x0,MAX_MSG);//Sanity
/* receive message */
cliLen = sizeof(cliAddr);
n = recvfrom(sd, msg, MAX_MSG, flags,(struct sockaddr *) &cliAddr, (socklen_t * )&cliLen);
if(n<0){printf("%s: cannot receive data \n",argv[0]);continue;}
//Received message
printf("%s: from %s:UDP%u : %s \n", argv[0],inet_ntoa(cliAddr.sin_addr),ntohs(cliAddr.sin_port),msg);
sleep(1);
//Sending back the data thus received
sendto(sd,msg,n,flags,(struct sockaddr *)&cliAddr,cliLen);
}//while
return 0;
}
This code work well & I can receive the packet to the server when some local client on the Linux machine tries to contact my server.
PROBLEM : When I make the same client in Android AVD present in my windows 7 system I am unable to reach my server.
I thought may be that's firewall issue, so I removed the firewall & added by pass custom rules to the IP "192.168.2.2" as given in the following link. http://www.brighthub.com/computing/windows-platform/articles/40014.aspx#
But it did not work. I thought that first I should try with raw java first then with AVD.
Hence, I created a UDP client with Java code still I was not able to connect to server.
Then I thought let's try with raw C++ so that I would come to know exactly what is the problem. Following is the Visual Studio code which I implemented for the same.
#define PORT_NUM 9999 // Port number used
#define IP_ADDR "192.168.2.2" // IP address of server1
#define BUFFER_SIZE 4096
void main(void){
WORD wVersionRequested = MAKEWORD(2,2); // Stuff for WSA functions
WSADATA wsaData; // Stuff for WSA functions
int client_s; // Client socket descriptor
struct sockaddr_in server_addr; // Server Internet address
int addr_len; // Internet address length
char out_buf[BUFFER_SIZE]; // Output buffer for data
char in_buf[BUFFER_SIZE]; // Input buffer for data
int retcode; // Return code
// This stuff initializes winsock
WSAStartup(wVersionRequested, &wsaData);
client_s = socket(AF_INET, SOCK_DGRAM, 0);
if (client_s < 0){ printf("*** ERROR - socket() failed \n"); exit(-1);}
server_addr.sin_family = AF_INET; // Address family to use
server_addr.sin_port = htons(PORT_NUM); // Port num to use
server_addr.sin_addr.s_addr = inet_addr(IP_ADDR); // IP address to use
strcpy(out_buf, "Test message from CLIENT to SERVER");
retcode = sendto(client_s, out_buf, (strlen(out_buf) + 1), 0,(struct sockaddr *)&server_addr, sizeof(server_addr));
if (retcode < 0){printf("*** ERROR - sendto() failed \n");exit(-1);}
addr_len = sizeof(server_addr);
retcode = recvfrom(client_s, in_buf, sizeof(in_buf), 0,(struct sockaddr *)&server_addr, &addr_len);
if (retcode < 0){printf("*** ERROR - recvfrom() failed \n");exit(-1);}
printf("Received from server: %s \n", in_buf);
retcode = closesocket(client_s);
if (retcode < 0){ printf("*** ERROR - closesocket() failed \n");exit(-1);}
WSACleanup();
}
But it gives me error of destination unreachable.
To find out exactly what is going on at the packet level, I installed "Wireshark", on my ubuntu machine.
My observation is... whenever my windows client executes I get a ICMP message 3 times on the Wireshark having the type 3 message. The detailed analysis of the packet showed that the port is unreachable.
Kindly help me to find out what I am missing here :(.
Have you tried disabling the firewall on the linux machine, or adding an exception for the port you are using?
sudo ufw disable
or use the following to show your iptables firewall rules:
sudo iptables -L
Check the connection between the two machines
ICMP: ping win->lin and back
TCP: connect SSH, Samba, or even browser if you can run some web server
UDP: use nc (netcat) utility to test UDP/TCP connection between two machines
If one of these does not work, look for the problem :
Shut down the firewalls on both computers and on the wireless AP, run sniffers on Win and on Lin machines.
If the connection is ok, the you know you have a bug in your program. Start debugging each end against something working - i.e. nc.
Hi
I am trying to write a multicast client on a machine with two NICs, and I can't make it work.
I can see with a sniffer that once I start the program the NIC (eth4) start receiving the multicast datagrams, However, I can't recieve() any in my program.
when running "tshark -i eth4 -R udp.port==xxx (multicast port)"
I get:
1059.435483 y.y.y.y. (some ip) -> z.z.z.z (multicast ip, not my eth4 NIC IP) UDP Source port: kkk (some other port) Destination port: xxx (multicast port)
Searched the web for some examples/explanations, but it seems like I do what everybody else does.
Any help will be appreciated...
Thanks!
bool connectionManager::sendMulticastJoinRequest()
{
struct sockaddr_in localSock;
struct ip_mreqn group;
char* mc_addr_str = SystemManager::Instance()->getTCP_IP_CHT();
char* local_addr_str = SystemManager::Instance()->getlocal_IP_TOLA();
int port = SystemManager::Instance()->getTCP_Port_CHT();
/* Create a datagram socket on which to receive. */
CHT_UDP_Feed_sock = socket(AF_INET, SOCK_DGRAM, 0);
if(CHT_UDP_Feed_sock < 0)
{
perror("Opening datagram socket error");
return false;
}
/* application to receive copies of the multicast datagrams. */
{
int reuse = 1;
if(setsockopt(CHT_UDP_Feed_sock, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) < 0)
{
perror("Setting SO_REUSEADDR error");
close(CHT_UDP_Feed_sock);
return false;
}
}
/* Bind to the proper port number with the IP address */
/* specified as INADDR_ANY. */
memset((char *) &localSock, 0, sizeof(localSock));
localSock.sin_family = AF_INET;
localSock.sin_port = htons(port);
localSock.sin_addr.s_addr =inet_addr(local_addr_str); // htonl(INADDR_ANY); //
if(bind(CHT_UDP_Feed_sock, (struct sockaddr*)&localSock, sizeof(localSock)))
{
perror("Binding datagram socket error");
close(CHT_UDP_Feed_sock);
return false;
}
/* Join the multicast group mc_addr_str on the local local_addr_str */
/* interface. Note that this IP_ADD_MEMBERSHIP option must be */
/* called for each local interface over which the multicast */
/* datagrams are to be received. */
group.imr_ifindex = if_nametoindex("eth4");
if (setsockopt(CHT_UDP_Feed_sock, SOL_SOCKET, SO_BINDTODEVICE, "eth4", 5) < 0)
return false;
group.imr_multiaddr.s_addr = inet_addr(mc_addr_str);
group.imr_address.s_addr = htonl(INADDR_ANY); //also tried inet_addr(local_addr_str); instead
if(setsockopt(CHT_UDP_Feed_sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&group, sizeof(group)) < 0)
{
perror("Adding multicast group error");
close(CHT_UDP_Feed_sock);
return false;
}
// Read from the socket.
char databuf[1024];
int datalen = sizeof(databuf);
if(read(CHT_UDP_Feed_sock, databuf, datalen) < 0)
{
perror("Reading datagram message error");
close(CHT_UDP_Feed_sock);
return false;
}
else
{
printf("Reading datagram message...OK.\n");
printf("The message from multicast server is: \"%s\"\n", databuf);
}
return true;
}
Before the call to IP_ADD_MEMBERSHIP set up group like this:
group.imr_multiaddr.s_addr = inet_addr(mc_addr_str);
group.imr_address.s_addr = inet_addr(local_addr_str);
You can leave the call to SO_BINDTODEVICE in before that, but that's only necessary if you would only like to use one specific interface.
I set up the group exactly like that (code is updated).
I also add to the routing table "route add -net 224.0.0.0 netmask 240.0.0.0 dev eth4"
still, with no success.
anything else I need to set up in my environment besides that?
I have a connection protocol that has been defined by our customer. Data are sent between two linux computers using UDP and TCP protocols. The IP addresses and ports are fixed on startup.
We are sending messages at 200 Hz and I have been using connect to save some time on the transmissions.
My problem is that if there is a communication error, I need to tear down the connections and reinitialise.
I have a problem with one of the UDP connections as it will not rebind to the required address and returns errno 22.
The code I am using is something like:
int
doConnect(int& sock, int local_port, char *local_ip, int remote_port, char *remote_ip)
{
sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
struct sockaddr_in addr;
memset(&addr, 0, sizeof(sockaddr_in);
addr.sin_family = AF_INET;
addr.sin_port = htons(local_port);
inet_pton(local_ip,&addr.sin_addr.s_addr);
if (0 > bind(sock, (struct sockaddr*)&addr, sizeof(addr)))
{
printf("Bind Error errno = %d\n", errno);
return ERR_BIND;
}
memset(&addr, 0, sizeof(sockaddr_in);
addr.sin_family = AF_INET;
addr.sin_port = htons(remote_port);
inet_pton(remote_ip,&addr.sin_addr.s_addr);
if (0 > connect(sock, (struct sockaddr*)&addr, sizeof(addr)))
{
printf("Connect Error errno = %d\n", errno);
return ERR_CONNECT;
}
return ERR_OK;
}
The way that this is used is like this:
int s1(-1), s2(-1);
doConnect(s1, 31003, "172.17.21.255", 31006, "172.17.21.1");
doConnect(s2, 31001, "172.17.21.3", 31004, "172.17.21.1");
When an error occurs
close(s1);
close(s2);
doConnect(s1, 31003, "172.17.21.255", 31006, "172.17.21.1");
doConnect(s2, 31001, "172.17.21.3", 31004, "172.17.21.1");
Here the local address is 172.17.21.3 and I am connecting to 172.17.21.1. s1 listens to a broadcast message.
s1 successfully reconnects to the remote machine, but s2 fails with error 22 from the call to bind.
I have tried explicitly calling bind and connect to an AF_UNSPEC address immediately before I close the socket. This doesn't solve the problem.
Are there any options that I should be using?
Perhaps you could try:
int val = 1;
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
I also suggest you double check that you're not passing the same socket to the two consecutive doConnect() calls (as errno 22 = EINVAL, which in the case of bind() appears to mean that the socket is already bound to an address).
The underlying socket layer might hold the port & IP address still open, even after your call to close. Try some of the following:
do a sleep(10) (or more) between the close and the call to doConnect again
configure the sockets using setsockopt with the SO_LINGER set to off
This actually happens more commonly with TCP connections, but I see no reason UDP can't have this problem as well.