I am trying to write a program for my raspberry pi that changes its system time to the time from a GPS unit on the same network. The GPS sends out a 72 byte UDP packet across port 3000. I am new to socket programming so I am unsure where I am going wrong.
The trouble that I am having is that I can't seem to get it to build with g++. I am getting the following error:
So the main error seems to be in the line
char A = struct sockaddr_in address;
Here is the start of my program and the method where I create the socket and where the error is located, if you would like the main method of my program then I will add it too.
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include <sys/time.h>
#include <errno.h>
#include <math.h>
// defines the socket used by the GPS
#define PORT 3000
/****************************/
int CreateSocket(int port)
/****************************/
{
// Create an UDP-socket
int sock = socket(AF_INET, SOCK_DGRAM, 0);
// Check if UDP-socket was created
if(sock==-1)
{
fprintf(stderr, "1CreateSocket: socket failed\n");
return -1;
}
// Bind it to the local IP-address
struct sockaddr_in address;
char A = struct sockaddr_in address;
fprintf(stderr, A);
// Pointer to the block of memory to fill with address data
memset(&address, 0, sizeof(address));
address.sin_family = AF_INET; // Address family for IP-address
address.sin_addr.s_addr = htonl(INADDR_ANY); // converts the unsigned integer hostlong from host byte order to network byte order
address.sin_port = htons(port); // converts the unsigned short integer hostshort from host byte order to network byte order
// Check if IP-address is correct, if not Socket failed. Otherwise it returns the socket
if(bind(sock, (struct sockaddr *) &address, sizeof(address))==-1)
{
fprintf(stderr, "2CreateSocket: bind failed\n");
close(sock);
return -1;
}
return sock;
}
Can anyone see any obvious errors here? Thanks
You don't really need these two lines:
char A = struct sockaddr_in address;
fprintf(stderr, A);
You can delete them, since they don't do anything useful, and they have a syntax error.
And to do some extra cleanup, the comment of the binding above those lines that can be deleted should actually go above the call to bind().
Related
I have made a pretty simple http client which would retrieve html from http website and print it. But there seems to be some problem while using connect() function.Using perror() I found that it is giving connection refused error.
This is my code
#include <string.h>
#include <stdio.h>
#include <iostream>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main(int argc, char *argv[])
{
char *address;
address = argv[1];
int c_socket = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in URLaddress;
URLaddress.sin_family = AF_INET;
URLaddress.sin_port = htons(80);
inet_pton(0,address,&URLaddress.sin_addr.s_addr);
int con = connect(c_socket, (struct sockaddr*) &URLaddress,
sizeof(URLaddress));
perror("error");
return 0;
}
This is the input
151.101.13.5
This is the output
error: Connection refused
I am passing IP of website as input.
I have seen all other similar questions but didn't get any answer as how to fix this because this keeps happening with every website I try my program with.
Please tell how to resolve this.
The following version of the code works on Windows/MSC:
int test(void)
{
char *address;
int c_socket, con;
struct sockaddr_in URLaddress;
char request[] = "GET / HTTP/1.1\r\n\r\n";
char response[4096];
WORD wVersionRequested;
WSADATA wsaData;
wVersionRequested = MAKEWORD( 2, 2 );
address = "151.101.13.5";
if (WSAStartup (wVersionRequested, &wsaData)!= 0) {
printf("DLL not found\n");
return -1;
}
if ((c_socket = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET ) {
printf("socket error: %d\n", WSAGetLastError());
return -1;
}
URLaddress.sin_family = AF_INET;
URLaddress.sin_port = htons(80);
URLaddress.sin_addr.s_addr= inet_addr(address);
con = connect(c_socket, (struct sockaddr*) &URLaddress, sizeof(URLaddress));
send(c_socket, request, strlen(request), 0);
recv(c_socket, response, sizeof(response), 0);
WSACleanup();
printf ("%s\n",response);
return 0;
}
The repsonse is:
<title>Fastly error: unknown domain </title>
</head>
<body>
<p>Fastly error: unknown domain: . Please check that this domain has been added to a service.</p>
<p>Details: cache-fra19128-FRA</p></body></html>5¸`¡qu
inet_pton(3) requires a first parameter to specify the address family and you have passed 0 for it (which is not the same as AF_INET), and you had to pass AF_INET, in accordance of the protocol family you are using.
inet_pton(3) is a protocol family independent conversion routine, but it needs to know what is the actual used to be able to convert addresses properly.
By the way, is a server listening on the requested address and port? have you tested that a browser is capable of getting something from that address before running your program?
#include <sys/socket.h>
#include <cstdio>
#include <stdlib.h>
#include <iostream>
#include <errno.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#define BUFSIZE 5000
#define PORT 80
using namespace std;
int main(int argc, char* argv[]){
char buffer[BUFSIZE];
int sockfd;
struct sockaddr_in their_addr;
if((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1){
perror("Socket generating failed");
exit(1);
}
their_addr.sin_family = AF_INET;
their_addr.sin_port = htons(PORT);
their_addr.sin_addr.s_addr = htonl(((struct in_addr*)gethostbyname("www.google.com")->h_addr_list[0])->s_addr);
if(connect(sockfd, (struct sockaddr*)&their_addr, sizeof(struct sockaddr)) == -1){ // stops at here!
perror("Connection failed");
exit(1);
}
close(sockfd);
return 0;
As a test of a combination of gethostbyname + connect, I wrote a simple code.
It queries the IP address of google by means of gethostbyname(), connects to google do nothing, and close the socket.
However, the program just stops at a line of the connect() function without any error including perror().
How can I fix this?
Get the s_addr, make sure it is an ipv4 address, and then on the command line try to ping that address with the command 'ping addr'
After that you could try a program like nmap but most likely ping will be enough.
There is probably nothing wrong with your code. You need to see if there is a proxy or firewall or anything else interfering with your network connection. You will also want to confirm you are getting an ipv4 address with gethostbyname
I solved this problem by removing htonl. I don't know why, and what could happen in future as a result of removing it. But this would be my best.
The socket API is not part of C++, it is posix. gethostbyname()is obsolete, use getaddrinfo instead. Read the appropriate man page, it also contains as example precisely the code you look for...
Below is the following basic socket code I came up with:
//General includes:
#include <iostream>
#include <stdio.h>
#include <string>
//Network related includes:
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
//Target host details:
#define PORT 1234
#define HOST "74.74.74.74"
using namespace std;
//Function prototypes:
string MessageFormat(int, char**);
void MessageSend(string);
int main(int argc, char *argv[])
{
//Parse arguments and format message:
string message = MessageFormat(argc, argv);
//Send the message out:
MessageSend(message);
return 0;
}
string MessageFormat(int argc, char *argv[])
{
//Massage the command line parameters
// into my desired payload format.
return message;
}
void MessageSend(string message)
{
int sd, ret;
struct sockaddr_in server;
struct in_addr ipv4addr;
struct hostent *hp;
sd = socket(AF_INET,SOCK_DGRAM,0);
server.sin_family = AF_INET;
inet_pton(AF_INET, HOST, &ipv4addr);
hp = gethostbyaddr(&ipv4addr, sizeof ipv4addr, AF_INET);
//hp = gethostbyname(HOST);
bcopy(hp->h_addr, &(server.sin_addr.s_addr), hp->h_length);
server.sin_port = htons(PORT);
connect(sd, (const sockaddr *)&server, sizeof(server));
send(sd, (char *)message.c_str(), strlen((char *)message.c_str()), 0);
}
This is quite basic, and does in fact work. HOWEVER, it's sending UDP packets instead of TCP packets, so the target host expecting TCP rejects these. Also, by inspecting connect/send values and watching my interfaces with ngrep I can 100% verify the packet is going out, so that's not the issue.
I'm only interested in modifying what I have, not creating a full featured server with boost asio. How can I tweak this so that it operates in terms of TCP instead of UDP?
Following are changes you need to make to transfer data via TCP
While creating socket pass correct parameters .In above example you passed SOCK_DGRAM instead pass SOCK_STREAM.
After binding server should go into listen mode (check the manual page of listen)
while Client Side should connect after socket creation.
Then accept in server side after listen.
Final Read and write to transfer data
Diagram attached will give you a clear picture of TCP connection
You can check manual pages for detailed info on all functions or refer beej's guide for socket programming ( use this link )
Replace SOCK_DGRAM with SOCK_STREAM.
Also, read the manual or get a good book.
I need to build a tool (c++) very much like "Wireless Network Watcher" which is a small utility that scans your wireless network and displays the list of all computers and devices that are currently connected to your network.
here's the existing tool http://www.nirsoft.net/utils/wireless_network_watcher.html
I need to know what are the win32 sdk functions to use to build this kind of functionality: scan the wireless network I am connected to and display all computers and devices connected to it.
ok, it seems is done this way: first sent an ARP request packet to each possible IP address in the network (you calculate them based on the net mask and the interface ip), for this step you can use SendARP functions. Then you have to call getnameinfo for each IP that responded previously, or you can send an NetBios request packet (port 137) to retreive the name of the device, if it has one, or know how to respond to that request.
for some networks this can take awhile (very long time).
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <netinet/ip_icmp.h>
#include <time.h>
#include <fcntl.h>
#include <signal.h>
#include <time.h>
// Define the Packet Constants
// ping packet size
#define PING_PKT_S 64
// Automatic port number
#define PORT_NO 0
// Automatic port number
#define PING_SLEEP_RATE 1000000
// Gives the timeout delay for receiving packets
// in seconds
#define RECV_TIMEOUT 1
// Performs a DNS lookup
char* dns_lookup(char* addr_host, struct sockaddr_in* addr_con) {
// printf("\nResolving DNS..\n");
struct hostent* host_entity;
char* ip = (char*)malloc(NI_MAXHOST * sizeof(char));
int i;
if ((host_entity = gethostbyname(addr_host)) == NULL) {
// No ip found for hostname
return NULL;
}
// filling up address structure
strcpy(ip, inet_ntoa(*(struct in_addr*)host_entity->h_addr));
(*addr_con).sin_family = host_entity->h_addrtype;
(*addr_con).sin_port = htons(PORT_NO);
(*addr_con).sin_addr.s_addr = *(long*)host_entity->h_addr;
return ip;
}
// Resolves the reverse lookup of the hostname
char* reverse_dns_lookup(char* ip_addr) {
struct sockaddr_in temp_addr;
socklen_t len;
char buf[NI_MAXHOST], *ret_buf;
temp_addr.sin_family = AF_INET;
temp_addr.sin_addr.s_addr = inet_addr(ip_addr);
len = sizeof(struct sockaddr_in);
if (getnameinfo((struct sockaddr*)&temp_addr, len, buf, sizeof(buf), NULL, 0,
NI_NAMEREQD)) {
// printf("Could not resolve reverse lookup of hostname\n");
return NULL;
}
ret_buf = (char*)malloc((strlen(buf) + 1) * sizeof(char));
strcpy(ret_buf, buf);
return ret_buf;
}
// Driver Code
int main(int argc, char* argv[]) {
int sockfd;
char *ip_addr, *reverse_hostname;
struct sockaddr_in addr_con;
int addrlen = sizeof(addr_con);
char net_buf[NI_MAXHOST];
int i = 0;
for (int i = 1; i < 255; ++i) {
char ip[80];
sprintf(ip, "192.168.2.%d", i);
ip_addr = dns_lookup(ip, &addr_con);
if (ip_addr == NULL) {
// printf("\nDNS lookup failed! Could not resolve hostname!\n");
continue;
}
reverse_hostname = reverse_dns_lookup(ip_addr);
if (reverse_hostname == NULL) {
// printf("\nDNS lookup failed! Could not resolve hostname!\n");
continue;
}
// printf("\nTrying to connect to '%s' IP: %s\n",ip, ip_addr);
printf("\nReverse Lookup domain: %s", reverse_hostname);
printf("\n %s \n", ip);
}
return 0;
}
result:
Reverse Lookup domain: router.asus.com
192.168.2.1
Reverse Lookup domain: DESKTOP-CMK0J2S
192.168.2.10
Reverse Lookup domain: User255
192.168.2.14
Very vague question, there is no single "find all devices" feature to Windows, wireless or even networking in general. You need to scan fer certain services like netbios (139), UPNP, etc. Also, none of this is specific to wireless conenctions.
In C++,
how can I get the receiver address of the UDP packet which I have received using recvfrom. I know that it should be the same host on which I am receiving the packet, but I need to extract it from the received packet, in order to verify something. How can I do this?
I found that one way of doing this is:
int r = getsockopt(receiver_sock, SOL_IP, SO_ORIGINAL_DST, (struct sockaddr *) &sender_addr, (socklen_t *)&addr_len);`
But I get the error:
error: ‘SO_ORIGINAL_DST’ was not declared in this scope
I am using the appropriate headers
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include </usr/src/linux-headers-2.6.32-21/include/linux/netfilter_ipv4.h>
#include <arpa/inet.h>
#include <linux/netfilter.h>
Using netfilter_ipv4 gives other errors like INT_MIN not declared. However, I think the mistake is something more fundamental rather than inclusion of proper header.
Please help.
On Linux you want to use IP_PKTINFO option, see ip(7), and the recvmsg(2) call.
Stevens has examples of doing this but with IP_RECVDSTADDR and IP_RECVIF options that are not available on Linux.
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
int opt = 1;
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
}