I have written a UDP broadcaster program to broadcast packets on the subnet 192.168.1.255, port 19000 - let's say it runs on Machine A 192.168.1.26. This is based on http://beej.us/guide/bgnet/html/single/bgnet.html#broadcast. With error checking removed, it looks like:
struct hostent* he = gethostbyname("192.168.1.255");
int fd = socket(AF_INET, SOCK_DGRAM, 0);
int broadcast = 1;
int errors = setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(int));
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr = *((struct in_addr*) he->h_addr);
memset(addr.sin_zero, '\n', sizeof(addr.sin_zero));
const char* message = "Hi there";
int len = strlen(message);
int bytes_sent = sendto(fd, data, len, 0, (struct sockaddr*) &addr, sizeof(addr));
I have written a corresponding receiver application to be distributed on machines on the same network as the broadcaster. This is based on http://beej.us/guide/bgnet/html/single/bgnet.html#datagram. Again, with error checking removed, this program looks like this:
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_PASSIVE;
struct addrinfo* servinfo;
int rv = getaddrinfo(NULL, "19000", &hints, &servinfo);
int fd = -1;
struct addrinfo* p;
for (p = servinfo; p != NULL; p = p->ai_next)
{
fd = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
int errors = bind(fd, p->ai_addr, p->ai_addrlen);
int broadcast = 1;
errors |= setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(int));
if (errors == 0)
break;
}
freeaddrinfo(servinfo);
struct sockaddr their_addr;
socklen_t addr_len = sizeof(their_addr);
int bufsize = 4096;
char buf[bufsize];
int bytes_received = recvfrom(fd, &buf[0], bufsize, 0, (struct sockaddr*) &their_addr, &addr_len);
When I run the broadcaster, in Wireshark I can see packets delivered to other machines on the subnet with the expected source address 192.168.1.26 and destination address 192.168.1.255. The payload is correct. However, my receiver application does not pick up the packets.
If I change the broadcaster to send only to a single receiver machine, e.g. 192.168.1.58, the receiver application on that machine receives the packets correctly but obviously no other machine does.
I have disabled the firewalls on both machines.
Can anyone suggest what's wrong?
Related
I'm trying to mmap tcp client using following code:
sockaddr_in addr,peer;
int server = socket(AF_INET, SOCK_STREAM, 0);
int value = 1;
assert(setsockopt(server, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(value)) != -1 );
assert(setsockopt(server, SOL_SOCKET, SO_REUSEPORT, &value, sizeof(value)) != -1 );
addr.sin_port = htons(8080);
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
assert(bind(server, (sockaddr*) &addr, sizeof(addr)) != -1 );
assert(listen(server, 5) != -1 );
socklen_t len;
int client = accept(server, (sockaddr *)&peer,&len);
assert(client != -1);
char *ip = inet_ntoa(peer.sin_addr);
int port = htons(peer.sin_port);
printf("Client accepted: %s:%d\n",ip,port );
auto mapped = (char*) mmap(0, 4096, PROT_READ | PROT_WRITE, MAP_SHARED , client, 0);
assert(mapped != (char*) -1); //mmap returns -1
char *str = "Hello client\n";
memcpy(mapped, str, strlen(str)); // send message to client
But mmap returns -1 when client connects.
So is there another way how to mmap client fd or is not possible.
I am trying to send a broadcast UDP package to all my Lifx devices (wifi lamps). The devices should answer with another package to the same port I sent the first package from.
I am so far, that I see my sent broadcast package in wireshark. I also see the reply from the Lifx lamp.
But my program is stuck on recvfrom.
int sockfd;
struct sockaddr_in saddr_send, saddr_recv;
if ((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0 ) {
perror("socket creation failed");
exit(EXIT_FAILURE);
}
int one = 1;
if ((setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void*) &one, sizeof(one))) < 0 ) {
perror("set socket option failed");
exit(EXIT_FAILURE);
}
if ((setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &one, sizeof(one))) < 0 ) {
perror("set socket option failed");
exit(EXIT_FAILURE);
}
memset(&saddr_send, 0, sizeof(saddr_send));
memset(&saddr_recv, 0, sizeof(saddr_recv));
// Filling dest information
saddr_send.sin_family = AF_INET; // IPv4
saddr_send.sin_addr.s_addr = INADDR_BROADCAST;
saddr_send.sin_port = htons(PORT);
// Filling source information
saddr_recv.sin_family = AF_INET; // IPv4
saddr_recv.sin_addr.s_addr = INADDR_ANY;
saddr_recv.sin_port = htons(PORT);
// Bind the socket with the server address
if (bind(sockfd, (const struct sockaddr *)&saddr_recv, sizeof(saddr_recv)) < 0 ) {
perror("bind failed");
exit(EXIT_FAILURE);
}
char buffer[BUFF_SIZE];
size_t length;
unsigned size = sizeof(saddr_recv);
char recvbuffer[BUFF_SIZE];
length = sendMessage->getEncodedHeader(buffer, BUFF_SIZE);
int e = sendto(sockfd, buffer, length, 0, (struct sockaddr*) &saddr_send, sizeof(saddr_send));
if (e < 0) {
printf("%i\n", errno);
perror("Send error: ");
}
unsigned int r = recvfrom(sockfd, (void*)&recvbuffer, sizeof(recvbuffer), 0, (struct sockaddr*)&saddr_recv, &size);
if (r < sizeof(lifx_protocol_header)) {
printf("package too short");
}
close(sockfd);
I am not sure if I made a conceptional mistake or if I am to slow with calling recvfrom.
Any idea on additional points I could try to solve my problem?
I have a software that decodes ADS-B messages (from planes) and sends results in hexadecimal to a port (47806).
I would like to listen to this port to show that data, so I wrote this :
WSADATA WSAData;
WSAStartup(MAKEWORD(2, 0), & WSAData);
SOCKET sock;
SOCKADDR_IN socket_in;
socket_in.sin_addr.s_addr = htonl(INADDR_ANY);
socket_in.sin_family = AF_INET;
socket_in.sin_port = htons(47806);
sock = socket(AF_INET, SOCK_STREAM, 0);
bind(sock, (SOCKADDR*)& socket_in, sizeof(socket_in));
listen(sock, 0);
int valid = 0;
while (TRUE) {
int size_socket_in = sizeof(socket_in);
valid = accept(sock, (SOCKADDR*)& socket_in, & size_socket_in);
if (valid != INVALID_SOCKET) {
std::cout << "OK";
}
}
This code should display "OK" each time a message is received, but it doesn't.
I can read data with a Telnet software, like PuTTY :
PuTTY telnet on port 47806
I don't understand why my code doesn't work.
Here's the right code :
WSADATA WSAData;
WSAStartup(MAKEWORD(2, 0), & WSAData);
SOCKET sock;
SOCKADDR_IN socket_in;
InetPton(AF_INET, "127.0.0.1", & socket_in.sin_addr.s_addr);
socket_in.sin_family = AF_INET;
socket_in.sin_port = htons(47806);
sock = socket(AF_INET, SOCK_STREAM, 0);
connect(sock, (SOCKADDR*)& socket_in, sizeof(socket_in));
int valid = 0;
char buffer[512] = "";
while (TRUE) {
valid = recv(sock, buffer, sizeof(buffer), 0);
if (valid != INVALID_SOCKET) {
std::cout << buffer;
}
}
My program is a client and not a server. So I have to define an IP adress with InetPton, connect to the server with connect and receive the messages with recv.
Thank you #Hasturkun and #RustyX for help and explanations.
I want to make sure that I understand the concept
we have example.exe and we will run it 5 times or more on the same computer
example.exe will create a pear (which has a sending and receiving socket)
and the sending socket sends on a fixed port and the receiving socket receive on the same port
my question is that when running example.exe 5 times
5 peers will be created on the same "machine" with the same fixed port !!! how that comes !
and i tried the code and it is working on the machine which means the same Ip address!
here are some code
Receiving Socket
sockaddr_in RecvAddr;
RecvAddr.sin_family = AF_INET;
RecvAddr.sin_port = htons(PORT);
RecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
cout << RecvAddr.sin_addr.s_addr << endl;
int broadcastValue = 1;
if (setsockopt(receivingSocket, SOL_SOCKET, SO_REUSEADDR, (char*)&broadcastValue, sizeof(broadcastValue)) == SOCKET_ERROR)
exit(EXIT_FAILURE);
int iResult = 0;
iResult = bind(receivingSocket, (SOCKADDR *)& RecvAddr, sizeof (RecvAddr));
if (iResult != 0) {
exit(EXIT_FAILURE);
Sending Socket
sockaddr_in destinationAddress;
destinationAddress.sin_family = AF_INET;
destinationAddress.sin_addr.s_addr = INADDR_BROADCAST;
destinationAddress.sin_port = htons((unsigned short)PORT);
if (sendto(sendingSocket, message.c_str(), message.length(), 0, (struct sockaddr*) &destinationAddress, sizeof(destinationAddress)) == SOCKET_ERROR)
{
exit(EXIT_FAILURE);
}
My teacher want us to do an exercise on raw socket in c ++ on Windows (for learning tcp communication).
I have got a problem with it. I saw a lot of documentation but I don't know how to solve it.
int raw()
{
WSADATA WSAData;
SOCKET sock;
SOCKADDR_IN sin,din;
WSAStartup(MAKEWORD(2, 2), &WSAData);
char datagram[MAX_PACKET_SIZE];
struct iphdr *iph = (struct iphdr *)datagram;
struct tcphdr *tcph = (struct tcphdr *)((UCHAR *)iph + sizeof(tcphdr));
char new_ip[sizeof "255.255.255.255"];
sock = socket(PF_INET, SOCK_RAW, IPPROTO_TCP);
if (sock == INVALID_SOCKET)
cout << "failled init socket" << endl ;
else{
memset(datagram, 0, MAX_PACKET_SIZE); // Clear the data
setup_ip_header(iph);
setup_tcp_header(tcph);
sin.sin_family = AF_INET;
sin.sin_port = htons(8888);
sin.sin_addr.s_addr = inet_addr("192.168.1.10"); //source ip
din.sin_family = AF_INET;
din.sin_port = htons(DEST_PORT);
din.sin_addr.s_addr = inet_addr(TARGET_SERV_IP); //ip serv to connect
tcph->port_dest = htons(DEST_PORT);
iph->ip_dest = din.sin_addr.s_addr;
iph->ip_source = sin.sin_addr.s_addr;
iph->ip_dest = inet_addr(TARGET_SERV_IP); //ip serv to connect
iph->ip_source = inet_addr("192.168.1.10"); //source ip
//iph->checksum = csum((unsigned short *)datagram, iph->tot_len >> 1);
iph->checksum = csum((unsigned short *)datagram, sizeof(struct iphdr));
int one = 1;
const int *val = &one;
if (setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char *)val, sizeof(one)) < 0)
printf("failled set socket option IP_HDRINCL");
else{
if (sendto(sock, /* our socket */
datagram, /* the buffer containing headers and data */
ntohs( iph->tot_len), /* total length of our datagram */
0, /* routing flags, normally always 0 */
(struct sockaddr *) &sin, /* socket addr, just like in */
sizeof(sin)) < 0) /* a normal send() */
cout << stderr << "sendto() error!!!.\n " << WSAGetLastError() << endl;
else
cout << "packet send\n" << endl;
}
closesocket(sock);
}
}
My error occurs at the sendto(). it return 10022 error = WSAEINVAL
I saw that can be a new windows protection?
Have you any idea to fix my problem or bypass the protection (go deeper, driver, etc)
You don't set iph->tot_len in your code.
My recommendation for networking code using c++ would be to use std::string or std::vector:
std::vector<uint8_t> packet(MAX_PACKET_SIZE, 0);
...
packet.resize(real_size);
then use the address (&packet[0]) for your pointer manipulations.