How do I send and receive UDP packets in QT - qt

I am writing a small application in QT that sends a UDP packet broadcast over the local network and waits for a UDP responce packet from one or more devices over the network.
Creating the sockets and sending the broadcast packet.
udpSocketSend = new QUdpSocket(this);
udpSocketGet = new QUdpSocket(this);
bcast = new QHostAddress("192.168.1.255");
udpSocketSend->connectToHost(*bcast,65001,QIODevice::ReadWrite);
udpSocketGet->bind(udpSocketSend->localPort());
connect(udpSocketGet,SIGNAL(readyRead()),this,SLOT(readPendingDatagrams()));
QByteArray *datagram = makeNewDatagram(); // data from external function
udpSocketSend->write(*datagram);
The application sends the packet properly and the response packet arrives but the readPendingDatagrams() function is never called. I have verified the packets are sent and received using Wireshark and that the application is listening on the port indicated in wireshark using Process Explorer.

I solved the problem. Here is the solution.
udpSocketSend = new QUdpSocket(this);
udpSocketGet = new QUdpSocket(this);
host = new QHostAddress("192.168.1.101");
bcast = new QHostAddress("192.168.1.255");
udpSocketSend->connectToHost(*bcast,65001);
udpSocketGet->bind(*host, udpSocketSend->localPort());
connect(udpSocketGet,SIGNAL(readyRead()),this,SLOT(readPendingDatagrams()));
QByteArray *datagram = makeNewDatagram(); // data from external function
udpSocketSend->write(*datagram);
The device on the network listens on port 65001 and responds to packets on the source port of the received packet. It is necessary to use connectToHost(...) in order to know what port to bind for the response packet.
It is also necessary to bind to the correct address and port to receive the packets. This was the problem.

You're binding your udpSocketSend in QIODevice::ReadWrite mode. So that's the object that's going to be receiving the datagrams.
Try one of:
binding the send socket in write only mode, and the receive one in receive only mode
using the same socket for both purposes (remove udpSocketGet entirely).
depending on your constraints.

For me, changing the bind from
udpSocket->bind(QHostAddress::LocalHost, 45454);
to simple
udpSocket->bind(45454);
does the trick!

Related

pcap_sendpacket dosent work on "Npcap Loopback Adapter"

I have installed npcap driver which supports loopback interface. I installed it because I need to inyect packets to loopback interface and read them from it. I can easily read packets in the loopback with "pcap_next_ex" as I can do in winpcap in ethernet interfaces, but when I want to inyect a packet to the loopback with "pcap_sendpacket" dosent work, and the function returns 0 (successfull).
I verified this by opening wireshark and watching the packets incoming to the interface, when I use pcap_sendpacket on ethernet interface I can watch the packets, but in the loopback they dont appear when I tried to inject them. Why?
//The array which contains the data of the test package
UCHAR packet[] = "\x..";
//loopback adapter is already opened here
for (int i = 0; i < 100; i++)
printf("%d ", pcap_sendpacket(loopbackAdapter, packet, sizeof(packet)));
I use this code on loopback interface and didnt work (but pcap_sendpacket returned always success), because in wireshark the packets didnt appear, but in ethernet interfaces the injection was successfull.
Does npcap support loopback packet inyection?
Thank you and regards!.
You need to understand that every network packet (even a loopback one) has a direction: on send path (Tx) or on receive path (Rx). Usually, when you send a packet to Npcap Loopback Adapter, you are actually sending it to the Tx path of the Windows TCP/IP stack. When you are sending Tx packets, you usually wait for a localhost application (or a protocol, a driver, etc) responding to them.
I don't know why you want to inject packets to loopback interface and read them from it. Npcap's low-level logic for this part is just not letting the current session (a pcap_t) receive the packets that this session injects. But other sessions can see them, this is why Wireshark can see the packets that you inject.
I just don't know why you are doing this. You seem not to want any other applications respond to these packets. But as a workaround, I think you can get what you want by injecting the packets to the Rx path. By sending packets to Rx, it means to fool Windows to believe that these packets are received from outside. I don't remember how I implement it, but the same session should be able to see these packets in Rx.
We didn't document the Rx feature very clearly. There's only some description in releases: v0.05-r6 and v0.05-r7, and an example here: https://github.com/hsluoyz/UserBridge. They should work even in latest Npcap.

TCP Messages are fragmented (split) in Win7 if datasize is more than 1074 bytes

I have used simple Socket class from .NET framework to send and receive data messages through TCP. When I run my tcp client app on Windows XP, then the data message is not fragmented (split). But when I run same tcp client app on Windows 7, the data messages are fragmented (split) when the data message size is more than 1074 bytes.
IPEndPoint ipEndPoint = new IPEndPoint("<server ip address>", 601);
Socket tcpSocket = new Socket(ipEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
tcpSocket.Connect(ipEndPoint.Address, ipEndPoint.Port);
tcpSocket .Send(data, data.Length, 0);
tcpSocket.Close();
Please let me know if you have any suggestions.
A TCP connection is a stream of bytes, it knows nothing of your message boundaries.
Any single read from a TCP connection can (and will) return between 1 byte and the size of the buffer supplied. This may change due to network conditions.
There is NO relationship between the amount of data written to a TCP connection by a particular call to Send() and the amount of data read from a connection by a call to Recv(),, except that all of the data written will be returned by a series of Recv calls.
You should always loop to receive data and use your own message framing to determine your message boundaries.
I wrote more about this here: http://www.codeproject.com/KB/IP/testingsocketservers.aspx back in 2002.

Sending packets via UDP in erlang

so i'm trying to send udp packet to a listening port on a computer which is not connected to the same LAN but has internet access via gen_udp in erlang.
I start my first node by opening the port
({ok, Socket} = gen_udp:open(8887).) and the open the port on the other node the same way, When i send a packet from one node to the other via gen_udp:send i don't receive anything (trying flush() on the receiving node), So i'm wondering if there is something i'm doing wrong ? , i checked the firewalls and erlang and epmd is permitted.
did you try setting the controlling process of the Socket as the current process via :
gen_udp:controlling_process(Socket,Pid) ?
You should then setup a receive loop and messages will be sent to you. The format of the messages should be : {udp, Socket, IP, InPortNo, Packet}
You could also try setting the socket to passive mode by using inet:setopts(Socket, [{active, false}]) after you have opened it. After which you can use 'gen_udp:recv/3` to read from the socket.

Wavecom GSM modem as a TCP client

I've been trying to do TCP communication using my Wavecom Fastrack modem. What I want to achieve is make the modem connect to a specified TCP server port to enable me to transfer data to and from the server. I found some information on than in the user's guide.
Basing on the information you can find on page 66 I created an application that opens the serial port to which the modem is connected and writes the following AT commands:
AT+WIPCFG=1 //start IP stack
AT+WIPBR=1,6 //open GPRS bearer
AT+WIPBR=2,6,11,"APN" //set APN of GPRS bearer
AT+WIPBR=2,6,0 //username
AT+WIPBR=2,6,1 //password
AT+WIPBR=4,6,0 //start GPRS bearer
AT+WIPCREATE=2,1,"server_ip_address",server_port //create a TCP client on port "server_port"
AT+WIPDATA=2,1,1 //switch do data exchange mode
This is exactly what the user's guide says. After the last command is sent to the modem, the device switches to data exchange mode and from then on everything what is written to the serial port opened by my application should be received by the server and everything the server sends should appear in the input buffer of that port.
The thing is that I did not manage to maintain stable bidirectional communication between the server and my modem. When I write some data to the serial port (only a few bytes), it takes a lot of time before the data appears on the server's side and in many cases the data does not reach the server at all.
I performed a few tests writing about 100 bytes to the serial port at once. Logging the data received by my server application I noticed that the first piece of data (8-35 bytes) is received after a second or two. The rest of the data appears in 2-5 seconds (either as a whole or in pieces of the said size) or does not appear at all.
I do not know where to look for the reason of that behaviour. Did I use wrong AT commands to switch the modem to TCP client mode? I can't believe the communication may be so slow and unstable.
Any advice will be appreciated. Thank you in advance.
what OS are you running? Windows does a pretty good job of hiding the messy details of communicating with the GPRS modem, all you have to do is create a new dial-up connection. To establish the connection you can make a call to the Win32 RasDial function. Once connected, you can use standard sockets to transfer data on a TCP port.
i have been using wavecomm modem for 2 years now.As far as i know from my experience is that if you are able to send some of the data then you can send all of the data.
the problem might be in the listening application which receives the data on the server side.
It could be that it is unable to deal with the amount of data that you are trying to send.
try sending the same data in smaller busts
with some delay in between them,then you might receive all data intact.

How to tell which interface the socket received the message from?

If a socket is bound to IN6ADDR_ANY or INADDR_ANY and you use a call such as recvfrom() to receive messages on the socket. Is there a way to find out which interface the message came from?
In the case of IPv6 link-scope messages, I was hoping that the from argument of recvfrom() would have the scope_id field initialized to the interface Id. Unfortunately it is set to 0 in my test program.
Anybody know of a way to find out this information?
dwc is right, IPV6_PKTINFO will work for IPv6 on Linux.
Moreover, IP_PKTINFO will work for IPv4 — you can see details in manpage ip(7)
I've constructed an example that extracts the source, destination and interface addresses. For brevity, no error checking is provided. See this duplicate: Get destination address of a received UDP packet.
// sock is bound AF_INET socket, usually SOCK_DGRAM
// include struct in_pktinfo in the message "ancilliary" control data
setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt));
// the control data is dumped here
char cmbuf[0x100];
// the remote/source sockaddr is put here
struct sockaddr_in peeraddr;
// if you want access to the data you need to init the msg_iovec fields
struct msghdr mh = {
.msg_name = &peeraddr,
.msg_namelen = sizeof(peeraddr),
.msg_control = cmbuf,
.msg_controllen = sizeof(cmbuf),
};
recvmsg(sock, &mh, 0);
for ( // iterate through all the control headers
struct cmsghdr *cmsg = CMSG_FIRSTHDR(&mh);
cmsg != NULL;
cmsg = CMSG_NXTHDR(&mh, cmsg))
{
// ignore the control headers that don't match what we want
if (cmsg->cmsg_level != IPPROTO_IP ||
cmsg->cmsg_type != IP_PKTINFO)
{
continue;
}
struct in_pktinfo *pi = CMSG_DATA(cmsg);
// at this point, peeraddr is the source sockaddr
// pi->ipi_spec_dst is the destination in_addr
// pi->ipi_addr is the receiving interface in_addr
}
Apart from binding to each interface, I'm not aware of a way with IPv4, per se.
IPv6 has added the IPV6_PKTINFO socket option to address this shortcoming. With that option in effect, a struct in6_pktinfo will be returned as ancillary data.
Its been a while since I've been doing C/C++ TCP/IP coding but as far as I remember on every message (or derived socket) you can get into the IP headers information. These headers should include the receiving address which will be the IP of the interface you are asking about.
Outside of opening a separate socket on each interface as Glomek suggested, the only way I know to do this definitively on Windows is to use a raw socket, e.g.,
SOCKET s = socket(AF_INET, SOCK_RAW, IPPROTO_IP);
Each receive from this socket will be an IP packet, which contains both the source and destination addresses. The program I work on requires me to put the socket in promiscuous mode using the SIO_RCVALL option. Doing this means I get every IP packet the interface "sees" on the network. To extract packets expressly for my application requires me to filter the data using the addresses and ports in the IP and TCP/UDP headers. Obviously, that's probably more overhead than you're interested in. I only mention it to say this - I've never used a raw socket without putting it in promiscuous mode. So I'm not sure if you can bind it to INADDR_ANY and just use it as a regular socket from that point forward or not. It would seem to me that you can; I've just never tried it.
EDIT: Read this article for limitations regarding raw sockets on Windows. This biggest hurdle I faced on my project was that one has to be a member of the Administrators group to open a raw socket on Windows 2000 and later.

Resources