I try to send hex data to another device. The compilation does not lead to errors. But when I launch the function from the terminal nothing happens but a light should turn on. I put a cout on connect () to see if I have some connection problems but it answers 0 (so I have no problems) maybe it's how I write the hex code?
Besides the code I also insert the command line that I execute with the Hex code. The strange thing is that if I use any program like PacketSender with the same parameters it works.
./main 192.168.2.170 26810000A7
in attachment I also add the screenshot made on PacketSender.In addition what I can say is that if I leave the recv () command in the code once I give the command from the terminal the prompt remains pending ... if instead I comment the recv () once I give the command from the prompt it returns to the prompt but without doing anything (so without turning on the light). Does anyone have any ideas?
enter image description here
#include <stdio.h>
#include <errno.h>
#include <string>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <cstring>
#include <unistd.h>
#include <iostream>
#include <unistd.h>
using namespace std;
// per compilare gcc connect_PE.cpp -lstdc++ -o main
int main(int argc, char *argv[])
{
int sockfd, n;
struct sockaddr_in servaddr;
std::string serveraddr = argv[1];
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = inet_addr(serveraddr.c_str());
servaddr.sin_port = htons(9761);
connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
cout << connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
const std::string hex = argv[2];
char *number = strcpy(new char[hex.length() + 1], hex.c_str());
send(sockfd, &number, 8, 0);
recv(sockfd, &number, 8, 0);
}
You’re passing the address of number when you should be passing its value.
Or even better, just pass hex.data() or &hex[0] – there’s no point in copying it.
Also note that you are sending a string of characters, not numbers in hexadecimal form.
(The first char is not 0x26 - that is, 38 - but ’2’, wich is probably 50.)
If you want to send the corresponding numbers, you need to convert the input first.
Sockets work very poorly with everything that is not char*, so it is better to immediately send a string from the terminal argument, and perform all the necessary transformations on the server.
Related
I'm developing an unique client that has to work on different machines. In every machine the server is running in a different IP address, but this address is known.
I don't want to tell the client which is the IP every time I run it, so I though about tell it in compilation time.
The problem is that when compiling with g++ -DHOSTNAME=127.0.0.1 (also tried with double quotes) the compiler is saying:
error: too many decimal points in number
./include/Client.h:18:25: note: in expansion of macro ‘HOSTNAME’
I tried it using localhost, too.
error: ‘localhost’ was not declared in this scope
./include/Client.h:18:25: note: in expansion of macro ‘HOSTNAME’
Also tried using some things found on the internet.
#define XSTR(x) STR(x)
#define STR(x)
compile error:
./src/BSCClient.cpp:15:45: note: #pragma message: HOSTNAME:
#pragma message("HOSTNAME: " XSTR(HOSTNAME))
./src/BSCClient.cpp:16:39: error: too few arguments to function ‘hostent* gethostbyname(const char*)’
server = gethostbyname(XSTR(HOSTNAME));
At this point I'm thinking that maybe macros isn't the proper way to handle this, but I don't figure out how to do it.
If someone has any reference about it I will be thankful.
EDIT:
These are the codes.
Client.h:
#ifndef __CLIENT_HH__
#define __CLIENT_HH__
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string>
#include <iostream>
using namespace std;
#define HOSTNAME 127.0.0.1
#define MAX_MESSAGE_LENGTH 10
class Client {
private:
string client_name;
int sockfd, portno;
struct sockaddr_in serv_addr;
struct hostent *server;
error(const char *msg);
public:
BSCClient (string name, int port);
void identifyme();
void sendData (string data);
string recvData ();
void closeSocket();
};
#endif
Client.cpp
#include "BSCClient.h"
#include <stdlib.h>
#include <time.h>
void BSCClient::error(const char *msg)
{
perror(msg);
exit(0);
}
Client::Client(string name, int port)
{
sockfd = socket(AF_INET, SOCK_STREAM, 0);
portno = port;
client_name = name;
if (sockfd < 0)
error("ERROR opening socket");
server = gethostbyname(HOSTNAME);
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr,
(char *)&serv_addr.sin_addr.s_addr,
server->h_length);
serv_addr.sin_port = htons(portno);
if (connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
error("ERROR connecting");
sendData(client_name);
}
void Client::identifyme() {
FILE *fp;
fp = popen("id -gn", "r");
char text[6];
fscanf(fp, "%s", text);
pclose(fp);
string data(text);
sendData(data);
}
void Client::sendData (string data) {
const char *sdata = data.c_str();
int n;
n = write(sockfd, sdata, strlen(sdata));
if (n < 0)
error("ERROR writing to socket");
}
string Client::recvData () {
int n;
int bytes;
char *longitud = new char[MAX_MESSAGE_LENGTH+1];
n = read(sockfd, longitud, MAX_MESSAGE_LENGTH);
if (n < 0) {
error("ERROR recieving size of output");
}
bytes=atoi(longitud);
//Para forzar el fin del string (ya que al imprimir el string hay veces que muestra caracteres de más)
longitud[MAX_MESSAGE_LENGTH]='\0';
char *data = new char[bytes];
n = read(sockfd, data, bytes);
if (n < 0)
error("ERROR reading output");
string ret(data);
return ret;
}
void Client::closeSocket() {
close(sockfd);
}
You have to escape the double quotes:
g++ -DHOSTNAME=\"127.0.0.1\"
Otherwise, the quotes are just saying to your shell that 127.0.0.1 is the value you want to give to -DHOSTNAME, which can be useful if the value has whitespaces for example:
g++ -DMAGIC_NUMBER="150 / 5"
(there, MAGIC_NUMBER will be replaced by 150 / 5 without the quotes)
If you want the quotes to be part of the macro (as in #define HOSTNAME "127.0.0.1"), you have to say to your shell that they are part of the value you give to -DHOSTNAME, this is done by escaping them.
EDIT:
Also, as pointed out by Angew, you misused the XSTR trick. It is an other solution to your problem than my answer.
It certainly works like this:
#define XSTR(x) STR(x)
#define STR(x) #x
With that you don't have to escape the quotes.
These two macros change the text 127.0.0.1 into "127.0.0.1". The XSTR macro allows HOSTNAME to be expanded to 127.0.0.1 before the STR macro converts it to "127.0.0.1". If you used directly the STR macro, you would end up with "HOSTNAME" instead of "127.0.0.1".
I think I prefer the escaping solution to the use of a trick involving two macros in the code, but that works too.
It seems odd that you'd want to hard-code this into the executable. It should be more flexible to use something like getenv("MY_SERVER_ADDR") and just set that environment variable before running your server. Or of course you could do the more typical thing and take it as a command line argument, but something tells me you already decided not to do that.
A slightly weirder idea if you are on Linux is to write the IP address into a text file and create an ELF object file from that using ld and objcopy; you can then load this into your app as a shared object or even a static one if you really want to "hard code" it. But I'm not sure why this would be preferable to the previously mentioned options.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I have a http server written in C which I plan to use for processing all requests in an ios app I'm building. When opening a html file with fopen() that is formatted for readability for example:
<html>
<body>
<h1>Hello World</h1>
</body>
</html>
I get a blank web page. However, if I write everything on one line it works fine.
For example:
<html><body><h1>Hello World</h1></body></html>
I was thinking that maybe I should remove all the white space before trying to send the file but then I would have to account for leaving the spaces between words and tag attributes.
I'm unsure of the proper way to send html files with return characters at the end of each line. Can someone explain why I'm getting a blank web page?
Here is my basic http server:
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#define DEFAULT_PORT 3015
#define IP "198.58.105.140"
int main()
{
FILE *html_data;
html_data = fopen("index.html", "r");
char response_data[1024];
fgets(response_data, 1024, html_data);
char http_header[2048] = "HTTP/1.1 200 OK\r\n\n";
strcat(http_header, response_data);
struct sockaddr_in addr;
unsigned int addrlen = sizeof(addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(DEFAULT_PORT);
addr.sin_addr.s_addr = INADDR_ANY; //inet_pton(AF_INET, IP, &(addr.sin_addr));
int socketListener = socket(AF_INET, SOCK_STREAM, 0);
bind(socketListener, (struct sockaddr*)&addr, addrlen);
listen(socketListener, SOMAXCONN);
int newConnection;
while(1)
{
newConnection = accept(socketListener, NULL, NULL);
send(newConnection, http_header, sizeof(http_header), 0);
//close(newConnection);
}
return 0;
}
fgets() just reads one line from the file. That's why your server works when the file has everything on one line. When you spread it over multiple lines, you only send the first line, which is just <html>, so there's nothing for the browser to display.
Use fread() to read more:
int size = fread(response_data, sizeof response_data - 1, 1, html_data);
response_data[size] = 0; // Add null terminator to string
And when you send the data, you shouldn't send past the null terminator. Use strlen() rather than sizeof() to get the number of valid characters.
send(newConnection, http_header, strlen(http_header), 0);
#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...
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().
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.