I got in my code a problem about sending something.
I got for example 2 Server.
This is Server 1:
unsigned int ip = 19216821;
unsigned int port = 4000;
char str[0];
sprintf(str, "%d", ip);
if ((dest_he=gethostbyname(str)) == NULL) { // get the host info
herror("gethostbyname");
exit(1);
}
dest_addr.sin_family = AF_INET;
dest_addr.sin_port = htons(port);
dest_addr.sin_addr = *((struct in_addr *)dest_he->h_addr);
memset(dest_addr.sin_zero, '\0', sizeof dest_addr.sin_zero);
then i want to send my buffer to dest_addr
if(sendto(sockfd, &buffer, sizeof(buffer),0, (struct sockaddr *)&dest_addr ,sizeof(struct sockaddr_storage)) == -1){
printf("error sending data\n");
return -1;
}
but I still get sendto(..) == -1.
My other Server is still waiting for an answer.
Server 2:
if(recvfrom(sockfd, &buffer, sizeof(buffer),0, (struct sockaddr *)&rand_addr ,&addr_size) == -1){
printf("error receiving data");
return -1;
}
I think my problem is that i setup the dest_addr wrong or?
First of all, your title doesn't really match your description. Nevertheless I'll make my best to answer your question.
Basically, you're not using correctly the function gethostbyname. As the name says it gets the host by its name not address. Hence, a correct usage would be:
struct hostent *host = gethostbyname("localhost");
To copy the result to your struct you can use:
memcpy(&dest_addr.sin_addr, host->h_addr_list[0], host->h_length);
On the other hand, if you want to send a message to a known IP-Address you can use:
char *ip = "127.0.0.1"
inet_aton(ip , &dest_addr.sin_addr)
Other than that everything looks fine. There are plenty of examples online on how to use TCP, UDP or even RAW sockets. I hope this was the answer you were expecting.
Related
I am exploring network programming in C.The code is supposed to connect to a server on port 80 send an http request and from the response print on what server is the web page running on, but it runs into Invalid Argument error. The error occurs with error message "[ERR] connecting to target server: Invalid argument" so the error should be somewhere in the connect() function.
rec = connect(sockfd, (struct sockaddr *)&target_addr, sizeof(struct sockaddr) == -1);
if(rec == -1)
fail("[ERR] connecting to target server");
Although I have seen a lot of similar issues, none of the fixes neither worked or applied to this case, strangely this code works as a standalone program when parsing argc[1] instead of char *name, regardless of what the exact string literal is(ip or hostname, experimented with multiple for both). The only difference between the two being that the entire web server function is written in main and passed command-line arguments(working example) while here it is written as a standalone function and called in main where it was tested on a few web page names and IP addresses.
Any help would be appreciated as I feel this might be some simple mistake I overlooked or something I don't understand well enough. Thanks!
int web_server(char *name){
int sockfd, rec;
struct hostent *host_info;
//struct in_addr *address;
struct sockaddr_in target_addr;
unsigned char buffer[4096];
if(is_ip(name)){
target_addr.sin_addr.s_addr = inet_addr(name);
} else if(host_info = gethostbyname(name)){
if(host_info == NULL){
fail("[ERR] looking up hostname!");
}else{
target_addr.sin_addr = *((struct in_addr *) host_info -> h_addr);
}
} else{
fail("[ERR] getting address");
}
target_addr.sin_family = AF_INET;
target_addr.sin_port = htons(80);
memset(&(target_addr.sin_zero), 0, 8);
sockfd = socket(PF_INET, SOCK_STREAM, 0);
if(sockfd == -1){
fail("[ERR] in socket");
}
rec = connect(sockfd, (struct sockaddr *)&target_addr, sizeof(struct sockaddr) == -1);
if(rec == -1)
fail("[ERR] connecting to target server");
send_string(sockfd, "HEAD / HTTP/1.0\r\n\r\n");
while(recv_line(sockfd, buffer)){
if(strncasecmp(buffer, "Server: ", 7) == 0){
printf("The web server for %s is %s\n", name, buffer+8);
}
}
close(sockfd);
printf("Server line not found\n");
exit(1);
}
int main(){
web_server("127.0.0.1");//doesn't work with hostnames either
}
I am setting up a Client Socket system, and the code all will make but the part referencing server_response. I am following a tutorial, but nobody else in the comments seemed to have this issue. What is causing this error and how do I fix it?
I was following this tutorial about halfway through I encountered this bug, and the issue is not addressed in the comments or in the video. https://www.youtube.com/watch?v=LtXEMwSG5-8
int network_socket;
network_socket = socket(AF_INET, SOCK_STREAM, 0);
//Address structure that holds access info for socket
struct sockaddr_in server_address;
server_address.sin_family = AF_INET; //specifies family or type of address, in this case an internet based one
server_address.sin_port = htons(13001); //specifies port
server_address.sin_addr.s_addr = INADDR_ANY;
//specifies socket, address point and the size of the address we are trying to connect to
//we save it as an int as if the connection is good it will return 0 if not it will be -1
int connection_status = connect(network_socket, (struct sockaddr *) &server_address, sizeof(server_address));
//checks for any error
if(connection_status == -1){
printf("There was an error connecting to the remote socket\n\n\n");
return 1;
}
//checks socket for any data size 250 chars long
char* server_response[300];
recv(network_socket, &server_response, sizeof(server_response), 0);
//prints data we get back
printf("server says:%s", server_response);
//closes socket
close(network_socket);
return 0;
}
char* server_response[300];
// ^
There should not be a * here. It's supposed to be an array of 300 chars. That way sizeof(server_response) in the following line will compute to 300 and recv() will read up to 300 bytes from the socket.
I server report need to display the clients ip address in the report which is processed by the server,that is i need to display from which client the report is being sent. How do i do this? Can anybody help me out?
use this :
char clntName[INET6_ADDRSTRLEN];
char portName[6];
if (getnameinfo(&client_address,
sizeof client_address,
clntName,
sizeof(clntName),
NULL,
0,
NI_NUMERICHOST|NI_NUMERICSERV|NI_NUMERICSCOPE) == 0) {
printf("Client = %s/%s\n",clntName,portName);
} else {
printf("Unable to get address\n");
}
The 'remoteIp' char array in following code will give you the client's ip address, whcih you can print using string functions. 'fd' is the listen socket for your server port..
struct sockaddr_in remoteAddr;
int size = sizeof(remoteAddr);
char remoteIp[10] = {0};
acceptFd = accept(fd, (struct sockaddr *)&remoteAddr, &size);
inet_ntop(AF_INET, &remoteAddr.sin_addr, remoteIp, INET_ADDRSTRLEN)
int createclientsock(char * hostname, int port){
struct hostent * hp;
printf("Attempting to create client socket!\n");
memset(&client_addr,'0',sizeof(client_addr));
client_addr.sin_family = AF_INET;
client_addr.sin_port = htons(port); /* holds the remote port */
/* If internet "a.d.c.d" address is specified, use inet_addr()
* to convert it into real address. If host name is specified,
* use gethostbyname() to resolve its address */
client_addr.sin_addr.s_addr = inet_addr(hostname); /* If "a.b.c.d" addr */
if (client_addr.sin_addr.s_addr == -1) {
hp = gethostbyname(hostname);
/* Call method to create server socketyname(hostname);*/
/*printf("host name: %s",hp);*/
if (hp == NULL) {
printf("ERROR: Host name %s not found\n", hostname);
exit(1);
}
}
/* Create an Address Family (AF) stream socket, implying the use of tcp as the underlying protocol */
client_fd = socket(AF_INET, SOCK_STREAM, 0);
printf("Client_fd: %d\n",client_fd);/*ANDY: it gets to here without printing errors, the client_fd = 3 ...im not sure what that means*/
/* use the sockaddr_in struct in the to variable to connect */
if (connect(client_fd, (struct sockaddr *)&client_addr, sizeof(client_addr)) < 0) {
printf("ERROR: could not connect!\n");
exit(1);
}
return client_fd;
}
It gets to the connect part and takes a long time before finally printing the error statement "ERROR: could not connect!\n"
Not sure if this is your actual problem but the line:
memset(&client_addr,'0',sizeof(client_addr));
is probably not what you want. It's fills the structure with the character '0' rather than zero bytes. It would be better written as:
memset(&client_addr,'\0',sizeof(client_addr));
In addition, if you use a DNS name rather than an IP address, you never load it into the client_addr structure. You get back the hostent pointer but you should then use the h_addr_list field in that structure to populate client_addr.sin_addr.s_addr.
I am writing a simple messaging application in C using sockets. When I use function recvfrom, it returns -1 and sets errno = 14 which is Bad address (which I am printing at the end).
The strange thing is that it still reads from the socket and gets the correct message. That is, the application is working perfectly and as expected except for that error.
My question is this: Why do you think I am getting this error? I cannot think of any reason. I was using inet_pton to set peer->sin_addr but I was getting the same error.
// socket file descriptor to send data through
int recv_sock_fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
// fill in the peer's address, loopback in this case
struct sockaddr_in *peer = malloc(sizeof(struct sockaddr_in));
peer->sin_family = AF_INET;
peer->sin_port = htons(11110);
char *new = &(peer->sin_addr);
new[0] = 127;
new[1] = 0;
new[2] = 0;
new[3] = 1;
for (int i = 0; i < 8; i++) {
peer->sin_zero[i] = NULL;
}
bind(recv_sock_fd, peer, sizeof(struct sockaddr_in));
// check to see if the socket has any data...code removed
char buff[32] = {0};
errno = 0;
int bytes_received = recvfrom(recv_sock_fd, buff, sizeof(buff), NULL, (struct sockaddr *)peer, sizeof(struct sockaddr_in));
printf("Bytes recieved: %d: %d : %s\n", bytes_received, errno, strerror(errno));
Look at the signature of recvfrom(2):
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen);
Last argument is an address, while you are giving it a plain integer.
Then you're building of the IP address is wrong. Do use inet_pton(3), that's what it's for. Also check the return value of the bind(2), it's surely failing now.