I want to send/receive data from a device via UDP. The device acts as a server and if I send it a value it sends me some values back. First I write a little python code which works without any problems:
import socket
import time
UDP_IP = "192.168.42.33"
UDP_PORT = 5004
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(('',UDP_PORT))
while True:
MESSAGE = input('Write new message: ')
sock.sendto(bytes.fromhex(MESSAGE), (UDP_IP, UDP_PORT))
time.sleep(0.1)
data, addr = sock.recvfrom(1076)
a = len(data)
print ("Byte: ", data.hex()[46], data.hex()[47])
I can write a value to a register with this script and get an array with all updated register values from the device back. I write an equal program in c++:
#pragma once
#pragma comment(lib, "Ws2_32.lib")
#include <sdkddkver.h>
#include <WinSock2.h>
#include <Windows.h>
#include <iostream>
#include <string>
#define SCK_VERSION2 0x0202
#define BUFLEN 2048
using namespace std;
int main()
{
int inputI;
long SUCCESSFUL;
WSAData WinSockData;
WORD DLLVersion;
SOCKET sock;
char msg_input[] = { 0x60, 0x01, 0x00, 0x00}; //Write REG mode, 1 byte
char* SU_IP = "192.168.42.33"; //IP Address of Scanner Unit
u_short SU_PORT = 5004; //Port of Scanner Unit
SOCKADDR_IN ADDRESS;
char buf[BUFLEN];
int slen = sizeof(ADDRESS);
DLLVersion = MAKEWORD(2, 1);
SUCCESSFUL = WSAStartup(DLLVersion, &WinSockData);
sock = socket(AF_INET, SOCK_DGRAM, 0);
ADDRESS.sin_addr.s_addr = inet_addr(SU_IP);
ADDRESS.sin_family = AF_INET;
ADDRESS.sin_port = htons(SU_PORT);
connect(sock, (SOCKADDR*)&ADDRESS, sizeof(ADDRESS));
while (1)
{
cout << "Adresse des Registers (hex): ";
cin >> hex >> inputI;
msg_input[2] = inputI;
cout << "Wert des Registers (hex): ";
cin >> hex >> inputI;
msg_input[3] = inputI;
send(sock, msg_input, sizeof(msg_input), NULL);
//recv(sock, buf, BUFLEN, 0);
}
}
I am able to sent values and the device sends its register values back so the communication works (I checked this with wireshark). But I can't receive the data in my program. I oncomment the recv function because the program gets stuck at this point if I want to receive. The recvfrom() function doesn't work at this point too. I tried the bind() function instead of connect because in the python script it works with sock.bind. But than I cant send or receive. I was reading several posts about UDP receive function but can't find my mistake. Can someone help me?
The Python code binds to all existing local interfaces at port 5004, whereas the C code will implicitly bind to a local free port during the call to connect(), thus if the remote peer is hard-coded to respond to port 5004, the socket will not receive it.
You should add a call to bind() right after creating your socket:
bind(sock, (sockaddr *)&ADDRESS, sizeof(ADDRESS));
And see what happens :)
Related
I'm having issues working with a UDP socket in Windows. I have a separate application I'm trying to communicate with that outputs on port 1625 and receives on port 26027. I tried to make a simple executable that reads one message and sends one message. The read works fine, but the send ends up with a WSAEADDRNOTAVAIL (10049) error.
To troubleshoot I also tried the equivalent code in Linux with (using Windows Subsystem for Linux) on the same machine and it works fine. So I can't figure out what the issue is. I also tried disabling Windows Firewall but that didn't make a difference. Any suggestions would be appreciated.
The Windows Visual C++ code:
#pragma comment(lib, "Ws2_32.lib")
#include <iostream>
#include <WS2tcpip.h>
#define MAXLINE 1024
int main()
{
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
// Define local port address.
sockaddr_in local_port;
memset(&local_port, 0, sizeof(local_port));
local_port.sin_family = AF_INET;
local_port.sin_addr.s_addr = INADDR_ANY;
local_port.sin_port = htons(1625);
// Bind local socket.
int socket_id = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
bind(socket_id, (const struct sockaddr *)&local_port, sizeof(local_port));
// Receive UDP Port message.
char in_buffer[MAXLINE];
int num_bytes = recv(socket_id, (char *)in_buffer, MAXLINE, 0);
in_buffer[num_bytes] = '\0';
printf("Received : %s\n", in_buffer);
// Set up send destination port.
sockaddr_in dest_port;
memset(&dest_port, 0, sizeof(dest_port));
dest_port.sin_family = AF_INET;
dest_port.sin_addr.s_addr = INADDR_ANY;
dest_port.sin_port = htons(26027);
// Send UDP message to specific UDP port.
char out_buffer[] = "Test message";
int result = sendto(
socket_id, out_buffer, strlen(out_buffer), 0, (struct sockaddr *)&dest_port, sizeof(dest_port));
printf("Send result : %d -- WSA Error : %d\n", result, WSAGetLastError());
closesocket(socket_id);
return 0;
}
Terminal output from running this executable is:
Received : 5e4009df*755=-0.0028:761=0.6942
Send result : -1 -- WSA Error : 10049
The WSL linux C++ code (the same source code except for WSA includes and error output):
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define MAXLINE 1024
int main()
{
// Define local port address.
sockaddr_in local_port;
memset(&local_port, 0, sizeof(local_port));
local_port.sin_family = AF_INET;
local_port.sin_addr.s_addr = INADDR_ANY;
local_port.sin_port = htons(1625);
// Bind local socket.
int socket_id = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
bind(socket_id, (const struct sockaddr *)&local_port, sizeof(local_port));
// Receive UDP Port message.
char in_buffer[MAXLINE];
int num_bytes = recv(socket_id, (char *)in_buffer, MAXLINE, 0);
in_buffer[num_bytes] = '\0';
printf("Received : %s\n", in_buffer);
// Set up send destination port.
sockaddr_in dest_port;
memset(&dest_port, 0, sizeof(dest_port));
dest_port.sin_family = AF_INET;
dest_port.sin_addr.s_addr = INADDR_ANY;
dest_port.sin_port = htons(26027);
// Send UDP message to specific UDP port.
char out_buffer[] = "Test message";
int result = sendto(
socket_id, out_buffer, strlen(out_buffer), 0, (struct sockaddr *) &dest_port, sizeof(dest_port));
printf("Send result : %d\n", result);
close(socket_id);
return 0;
}
Terminal output from running this executable is:
Received : 5e4009df*755=-0.0028:761=0.6942
Send result : 12
I can also validate that the output to port 26027 via this Linux implementation is received by the other application and can also see it in Wireshark.
EDIT:
After Remy's answer below I was able to get this working as per the comments below. To clarify my network:
My network if I view it with Wireshark now looks like:
127.0.0.1 UDP 50223 → 1625 Len=32
127.0.0.1 UDP 1625 → 26027 Len=12
Where my node binds to 1625 where it can recv() UDP from some unknown port number (50223 in this case), and sendto() port 26027.
You can't use recv() with a UDP socket unless you first call connect() to statically assign the peer's IP/port to the socket, which you are not doing. So recv() will fail, but you are not checking for that. You need to use recvfrom() instead.
Also, no matter what, you can't send packets to INADDR_ANY (0.0.0.0) as you are. That is why you are getting the send error.
sendto Function
WSAEADDRNOTAVAIL
The remote address is not a valid address, for example, ADDR_ANY.
Windows Sockets Error Codes
WSAEADDRNOTAVAIL
10049
Cannot assign requested address. The requested address is not valid in its context. This normally results from an attempt to bind to an address that is not valid for the local computer. This can also result from connect, sendto, WSAConnect, WSAJoinLeaf, or WSASendTo when the remote address or port is not valid for a remote computer (for example, address or port 0).
You need to send to an actual IP/port, such as to the peer's IP/port that is reported by recvfrom() when it receives a packet.
I'm trying to get a little SSDP client / server up and running. So far the server is working just fine, responding to my M-SEARCH (according to wireshark). The client code is written in Visual Studio using Winsock2 (see code below). The problem is that the response never reaches my recv call when i send the search to the multicast address.
I already tried sending and receiving directly to the server ip address, which will generate a response that reaches my recv call correctly. However, when i change the ip to the multicast addess, it doesn't work (even though i can see the response on Wireshark!). So for some reason the socket (on OS level?) refuses to pass it on to the application.
I should note that the response is always unicast.
Here's my code:
#include <Winsock2.h> // before Windows.h, else Winsock 1 conflict
#include <Ws2tcpip.h> // needed for ip_mreq definition for multicast
#include <Windows.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#define SERVERPORT 1900
char buff[] = "M-SEARCH * HTTP/1.1\r\nHOST: 239.255.255.250:1900\r\nMAN: ssdp:discover\r\nST: ssdp:all\r\n\r\n";
int main()
{
char rcvdbuff[1000];
int len, Ret = 2;
WSADATA wsaData;
if (WSAStartup(0x0101, &wsaData)) {
perror("WSAStartup");
return 1;
}
struct sockaddr_in their_addr;
SOCKET sock;
sock = socket(AF_INET, SOCK_DGRAM, 0);
their_addr.sin_family = AF_INET;
////THIS APPROACH DOES NOT WORK
their_addr.sin_addr.s_addr = inet_addr("239.255.255.250");
//THIS APPROACH WORKS - SOMEHOW THE SOCKET IS BOUND TO THIS IP AND CAN THUS RECEIVE
//their_addr.sin_addr.s_addr = inet_addr("192.168.3.90");
their_addr.sin_port = htons(SERVERPORT);
len = sizeof(struct sockaddr_in);
while (1)
{
printf("buff:\n%s\n", buff);
Ret = sendto(sock, buff, strlen(buff), 0, (struct sockaddr*)&their_addr, len);
if (Ret < 0)
{
printf("error in SENDTO() function");
closesocket(sock);
return 0;
}
//Receiving Text from server
printf("\n\nwaiting to recv:\n");
memset(rcvdbuff, 0, sizeof(rcvdbuff));
Ret = recvfrom(sock, rcvdbuff, sizeof(rcvdbuff), 0, (struct sockaddr *)&their_addr, &len);
if (Ret < 0)
{
printf("Error in Receiving");
return 0;
}
rcvdbuff[Ret - 1] = '\0';
printf("RECEIVED MESSAGE FROM SERVER\t: %s\n", rcvdbuff);
//Delay for testing purpose
Sleep(3 * 1000);
}
closesocket(sock);
WSACleanup();
}
I tried one interesting thing (without restarting the application!):
1) First send to the direct ip address (192.168.3.90)
2) Get response
3) Now send to the multicast address
4) Now the response gets back just fine!
It's as if the socket somehow 'knows' the unicast address from the first send/recv call.
Does anyone know what to do or how to debug?
I think I've found the solution to the question: Windows Firewall.
Here's a quote over from Quora:
Only connections that are explicitly allowed, using firewall rules, are permitted. Windows Firewall, by default, allows all outboundconnections, and permits only established inbound connections (that is, an inbound connection that is in direct response to an outbound connection initiated from your computer or network).
This is exactly the situation: We've not established an outbound connection, and thus it's blocked by Windows Firewall!
In the other case, when I first send directly, Windows Firewall opens up for that exact inbound connection and therefore the subsequent multicast send gets a response.
I found that the behavior of iOS socket "sendto" interface was different from android or linux kernel. When we call "sendto",we start wireshark capture at the same time . But we can't find the capture data immediately. We make a test that we continuously sending 332 bytes by "sendto" per 40ms interval.And we found that all data packets was send to the network in a short central time instead of a 40MS(or above) intervals. We doubt that the ios kernal made some change for udp.Also it may calls audio delay about 900-1000ms.
I have test in iphone 5s & iphone 6,iOS 10 or 11 by demo use "sendto" api
#include <sys/socket.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <sys/types.h>
int sSock = socket(AF_INET,SOCK_DGRAM,0);
struct sockaddr_in localAddr;
localAddr.sin_family = AF_INET;
localAddr.sin_port = htons(1001);
localAddr.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(sSock, (struct sockaddr*)&localAddr, sizeof(localAddr)) < 0)
{
NSLog(#"bind error");
return;
}
struct sockaddr_in sendAddr;
sendAddr.sin_family = AF_INET;
sendAddr.sin_port = htons(21000);
inet_pton(AF_INET, "114.190.105.220", &sendAddr.sin_addr);
char sendBuf[332] = {0};
//unsigned char service_type = 0xe0 | IPTOS_LOWDELAY | IPTOS_RELIABILITY;
int service_type = 0x10;
int priority = 6;
//if(setsockopt(sSock, SOL_SOCKET, SO_PRIORITY, &priority, sizeof(priority))<0)
if(setsockopt(sSock,IPPROTO_IP,IP_TOS,(void*)(&service_type),sizeof(service_type)) < 0)
{
NSLog(#"setsockopt failed1,error[%s]",strerror(errno));
}
while(true)
{
sendto(sSock, sendBuf, sizeof(sendBuf), 0, (struct sockaddr*)&sendAddr, sizeof(sendAddr));
time_t timeNow;
time(&timeNow);
struct tm tmNow;
struct timeval tvNow;
localtime_r(&timeNow,&tmNow);
gettimeofday(&tvNow, NULL);
char sTime[256] = {0};
snprintf(sTime, sizeof(sTime)-1, "%04d%02d%02d %02d%02d%02d.%d",tmNow.tm_year+1900,tmNow.tm_mon,tmNow.tm_mday,tmNow.tm_hour,tmNow.tm_min,tmNow.tm_sec,tvNow.tv_usec/1000);
NSLog(#"[%s]interval 40ms send",sTime);
usleep(40*1000);
}
all data packets was send to the network in a short central time instead of a 40MS(or above) intervals.
all packets send at once,wireshark capture like this:
No. Time Protocol
819 41.439392 H264
820 41.439617 H264
821 41.439819 H264
I am using Raspberry Pi 3's internal bluetooth and I am writing a c++ code to connect the bluetooth of my windows PC. On the PC side, I use Matlab and I am able to send bytes to raspberry. However when I try to send bytes from raspberry to PC, I get the following error:
"Transport endpoint is not connected"
and Matlab says "Unsuccessful read: the specified amount of data was not returned within the timeout period".
Another interesting thing is that, when I try to send more than three bytes from Matlab, raspberry only receives the first three as if the rest did not exist. If I use two reads in a row, I am able to get 6 bytes and so on. Just pointing this odd fact since I thought it might be connected with my main problem and be a clue.
I have also tried to send a file manually, using the bluetooth symbol on menubar and it worked. So c++ code should be doing something different to cause this problem.
What is likely to be the cause of my problem? How can I send data from raspberry to my computer using c++?
My code is as follows:
(Referred website: http://people.csail.mit.edu/albert/bluez-intro/index.html)
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/rfcomm.h>
int main(int argc, char **argv)
{
struct sockaddr_rc loc_addr = { 0 }, rem_addr = { 0 };
char buf[1024] = { 0 };
int s, client, bytes_read;
socklen_t opt = sizeof(rem_addr);
// allocate socket
s = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
bdaddr_t tempBDADDR = {0};
// bind socket to port 1 of the first available
// local bluetooth adapter
loc_addr.rc_family = AF_BLUETOOTH;
loc_addr.rc_bdaddr = tempBDADDR;
loc_addr.rc_channel = (uint8_t) 1;
bind(s, (struct sockaddr *)&loc_addr, sizeof(loc_addr));
// put socket into listening mode
listen(s, 1);
// accept one connection
client = accept(s, (struct sockaddr *)&rem_addr, &opt);
ba2str( &rem_addr.rc_bdaddr, buf );
fprintf(stderr, "accepted connection from %s\n", buf);
memset(buf, 0, sizeof(buf));
// read data from the client
bytes_read = read(client, buf, sizeof(buf));
if( bytes_read > 0 ) {
printf("received [%s]\n", buf);
}
int status = 0;
// send a message
if( status == 0 ) {
status = write(s, "hello!", 6);
}
if( status < 0 ) perror("uh oh");
// close connection
close(client);
close(s);
return 0;
}
Matlab side is as straight forward as:
b = Bluetooth('raspberrypi', 1);
fopen(b);
fwrite(b, uint('1234'));
input = fread(b,6)
fclose(b);
clear('b');
EDIT:
Just figured that I do not get the "Transport endpoint is not connected" when I use the following line. However this only allows me to connect as client, whereas matlab only has a client type of connection. So now, I am able to send data to my computer from another socket without getting any errors, but cannot read it with matlab.
status = connect(s, (struct sockaddr *)&addr, sizeof(addr));
Just figured it out. Leaving this here in case it helps someone else as well.
When a connection is accepted, a new descriptor is returned (along with a new socket). This is a significant difference from connect(). So I was wrong at the following line.
status = write(s, "hello!", 6);
changing it to
status = write(client, "hello!", 6);
worked like a charm.
(Reference: http://users.pja.edu.pl/~jms/qnx/help/tcpip_4.25_en/prog_guide/sock_advanced_tut.html)
I have the written the following code for transmitting UDP packets via broadcasting on a wireless network. The application that I have trying to develop requires the packets to be transmitted very fast, but unfortunately I cannot do so and need to add a sleep time. I find that below 500us sleep time, I am unable to send all the packets successfully.
Why does the sleep time have to be so high?
Is it possible to reduce this time by further optimization of this code?
If I do not process the received packets buffer, is it okay? Or does this create problems?
Note that I am running this code on a wireless radio which runs using OpenWrt.
Thanks in advance.
Code:
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <netdb.h>
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <sys/time.h>
#include <arpa/inet.h> /* for sockaddr_in */
#define BROADCAST_IP "192.168.255.255"
#define BROADCAST_PORT 45454
int b_sock=-1;
void init_socket()
{
unsigned short b_port = BROADCAST_PORT;
struct sockaddr_in b_addr;
int broadcastPermission;
char* rx_ip = BROADCAST_IP;
if ((b_sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
perror("socket() failed");
/* Set socket to allow broadcast */
broadcastPermission = 1;
if (setsockopt(b_sock, SOL_SOCKET, SO_BROADCAST, (void *) &broadcastPermission, sizeof(broadcastPermission)) < 0)
perror("setsockopt() failed");
int opts;
opts = fcntl(b_sock,F_GETFL);
if(opts < 0)
perror("fcntl get failed");
opts = (opts | O_NONBLOCK);
if(fcntl(b_sock,F_SETFL,opts) < 0)
perror("fcntl set failed");
memset(&b_addr, 0, sizeof(b_addr)); /* Zero out structure */
b_addr.sin_family = AF_INET; /* Internet address family */
b_addr.sin_addr.s_addr = inet_addr(rx_ip);/* Broadcast IP address */
b_addr.sin_port = htons(b_port); /* Broadcast port */
if (bind(b_sock, (struct sockaddr *) &b_addr, sizeof(b_addr)) < 0)
perror("rx bind() failed");
}
void send_thread_body(long int buf, struct sockaddr_in tx_addr)
{
if(sendto(b_sock, &buf, sizeof(long int), 0, (struct sockaddr *)&tx_addr, sizeof(tx_addr)) < 0)
printf("tx sent diff num bytes than expected: %d\n",buf);
}
int main(int argc, char *argv[])
{
init_socket();
{
timeval start, end;
double diff = 0;
long int num = 0;
char *tx_ip = BROADCAST_IP;
unsigned short tx_port = BROADCAST_PORT;
struct sockaddr_in tx_addr;
memset(&tx_addr, 0, sizeof(tx_addr)); /* Zero out structure */
tx_addr.sin_family = AF_INET; /* Internet address family */
tx_addr.sin_addr.s_addr = inet_addr(tx_ip);/* Broadcast IP address */
tx_addr.sin_port = htons(tx_port); /* Broadcast port */
double next = 0;
double st = 0;
while (num<50000)
{
while (st <= next)
{
gettimeofday(&start,NULL);
st = start.tv_sec*1000 + ((double)start.tv_usec)/1000.0;
}
send_thread_body(num,tx_addr);
gettimeofday(&end, NULL);
diff += ((double)(((end.tv_sec - start.tv_sec)*1000000 + (end.tv_usec - start.tv_usec))))/1000000.0;
num++;
next = end.tv_sec*1000 + ((double)end.tv_usec)/1000.0 + 0.7;
}
printf("Avg time diff: %f\n",diff/50000.0);
}
close(b_sock);
return 0;
}
You are probably overflowing the socket buffer because you set the socket to O_NONBLOCK. Normally (when blocking is enabled), if the socket buffer is full, sendto blocks until there is sufficient buffer space to hold the message for sending.
From http://pubs.opengroup.org/onlinepubs/009695399/functions/sendto.html:
If space is not available at the
sending socket to hold the message to
be transmitted and the socket file
descriptor does not have O_NONBLOCK
set, sendto() shall block until space
is available. If space is not
available at the sending socket to
hold the message to be transmitted and
the socket file descriptor does have
O_NONBLOCK set, sendto() shall fail.
When you added sleeps between your sendto calls, you were effectively throttling down the throughput and preventing the socket buffers from overflowing.
Instead of sleep, you should use a blocking socket. If the socket buffers become full, sendto will block, which is effectively the same thing as sleeping, except that it will automatically stop sleeping the instant the socket is able to hold your next datagram.
To achieve better thoughput, try lumping data into datagrams close to the MTU size (while taking care to save enough room for UDP/IP headers). This should give you smaller header overhead compared to sending very short datagrams.