Recv hangs even though I followed all conventions? - c

I am trying to create a small program that takes a http requests through stdin and sends it to a server.
This is the code I am using:
int portno = 3000;
char *message = buf;
char response[4096];
int byte_count;
fsize = strlen(message);
int sockfd;
/* fill in the parameters */
printf("Request:\n%s\n",message);
/* create the socket */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) error("ERROR opening socket");
int sz = (1024 * 1024);
if (setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &sz, sizeof(sz)) == -1) {
perror("setsockopt");
exit(1);
}
struct sockaddr_in saddr;
saddr.sin_family = AF_INET;
saddr.sin_port = htons(portno);
saddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
if (connect(sockfd, &saddr, sizeof(saddr)) == -1) {
perror("connect");
}
send(sockfd, message, fsize, MSG_NOSIGNAL);
printf("written");
byte_count = recv(sockfd,response,sizeof(response)-1,0); // <-- -1 to leave room for a null terminator
response[byte_count] = 0; // <-- add the null terminator
printf("recv()'d %d bytes of data in buf\n",byte_count);
printf("%s",response);
close(sockfd);
buf is equal to this
GET /alias%2Findex.html HTTP/1.0\r\n
\r\n
\r\n
\r\n
I have done some research through other stack overflow posts and they state that recv usually hangs when the system is waiting for a response. I do not know what could be causing this.

Here is your program only slightly modified. And it works for me.
Are you certain whatever server you are running on localhost port 3000 is responding properly? BTW, I had to change the port to 8080 for my system.
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
char buf[1 << 16] = "GET /file.txt HTTP/1.0\r\n"
"\r\n"
"\r\n";
int main() {
int portno = 8080;
char *message = buf;
int byte_count;
int fsize = strlen(message);
int sockfd;
/* fill in the parameters */
printf("Request:\n%s\n", message);
/* create the socket */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
perror("ERROR opening socket");
int sz = (1024 * 1024);
if (setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &sz, sizeof(sz)) == -1) {
perror("setsockopt");
exit(1);
}
struct sockaddr_in saddr;
saddr.sin_family = AF_INET;
saddr.sin_port = htons(portno);
saddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
if (connect(sockfd, (struct sockaddr *)&saddr, sizeof(saddr)) == -1) {
perror("connect");
}
send(sockfd, message, fsize, MSG_NOSIGNAL);
printf("written");
while ((byte_count = recv(sockfd, buf, sizeof(buf) - 1, 0)) >
0) { // <-- -1 to leave room for a null terminator
buf[byte_count] = 0; // <-- add the null terminator
printf("recv()'d %d bytes of data in buf\n", byte_count);
printf("%s", buf);
}
close(sockfd);
return 0;
}

Related

C Socket does not connect and returns exit value of 255

I have a piece of C code that should connect to www.google.com and make a HTTP GET request, but when I run it, it stays on "Connecting.." for about 30 seconds before returning "Connection Failed" and an exit return value of 255. What am I doing wrong?
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#define PORT 8000
struct hostent *hostinfo;
int main(void) {
int sock = 0, valread;
struct sockaddr_in serv_addr;
char *hostname = "www.google.com";
char *request = "GET / HTTP/1.1\r\nHost: www.google.com\r\n\r\n";
hostinfo = gethostbyname(hostname);
char *ip = inet_ntoa(*(struct in_addr*)hostinfo->h_addr_list[0]);
char buffer[1024] = {0};
printf("Creating socket...\n");
if((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0){
printf("\n Socket creation error \n");
return -1;
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
printf("Checking address...\n");
if(inet_pton(AF_INET, ip, &serv_addr.sin_addr) <= 0){
printf("\n Invalid IP/Address not supported \n");
return -1;
}
printf("Connecting to host %s...\n", ip);
if(connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0){
printf("\n Connection Failed \n");
return -1;
}
send(sock, request, strlen(request), 0);
printf("Message sent\n");
valread = read(sock, buffer, 1024);
printf("%s\n", buffer);
return 0;
}
I see two major problems.
You use the wrong port. Use port 80 for http.
Your read and printf is a dangerous combination that could easily cause access out of bounds (and undefined behavior). What you read from the socket will not be null terminated. You could instead do something like this:
...
printf("Message sent\n");
while((valread = read(sock, buffer, sizeof(buffer))) > 0) {
fwrite(buffer, valread, 1, stdout);
}
This will however block when everything has been read. See non-blocking I/O or consider using select, epoll or poll to wait for available data on sockets.
If you are only interested in getting the response and then disconnect, you could however use Connection: close to close the connection after the server has sent the response. Full code below:
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#define PORT 80
int main(void) {
int sock = 0, valread;
struct hostent *hostinfo;
struct sockaddr_in serv_addr;
const char *hostname = "www.google.com";
const char *request = "GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: close\r\n\r\n"; // <- added
hostinfo = gethostbyname(hostname);
char *ip = inet_ntoa(*(struct in_addr*)hostinfo->h_addr_list[0]);
char buffer[1024] = {0};
printf("Creating socket...\n");
if((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0){
printf("\n Socket creation error \n");
return -1;
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
printf("Checking address...\n");
if(inet_pton(AF_INET, ip, &serv_addr.sin_addr) <= 0){
printf("\n Invalid IP/Address not supported \n");
return -1;
}
printf("Connecting to host %s...\n", ip);
if(connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0){
perror("connect()");
return -1;
}
send(sock, request, strlen(request), 0);
printf("Message sent\n");
while((valread = read(sock, buffer, sizeof(buffer))) > 0) {
fwrite(buffer, valread, 1, stdout);
}
}

Could not able to do bidirectional multicast connection using UDP

Have to make it server & client as bidirectional where I should able to send & receive data in console.
I can able to send data from server to client but not able to receive any data from client.Stuck in this for long time could not know how to resolve it.
I just started working on networking any lead on this really helpful.
Here is my code.
Server.c
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
struct in_addr localInterface;
struct sockaddr_in groupSock, rcv_addr;
int sd;
char databuf[1024];
int datalen = sizeof(databuf);
int main(int argc, char *argv[])
{
/* Create a datagram socket on which to send. */
socklen_t rcv_addr_size = sizeof(struct sockaddr_in);
sd = socket(AF_INET, SOCK_DGRAM, 0);
if (sd < 0)
{
perror("Opening datagram socket error");
exit(1);
}
else
printf("Opening the datagram socket...OK.\n");
memset((char*) &groupSock, 0, sizeof(groupSock));
groupSock.sin_family = AF_INET;
groupSock.sin_addr.s_addr = inet_addr("226.1.1.1");
groupSock.sin_port = htons(4321);
localInterface.s_addr = inet_addr("127.0.0.1");
if (setsockopt(sd, IPPROTO_IP, IP_MULTICAST_IF, (char*) &localInterface,
sizeof(localInterface)) < 0) {
perror("Setting local interface error");
exit(1);
} else
printf("Setting the local interface...OK\n");
int read_size;
while (1) {
memset(databuf, 0x00, sizeof(databuf));
scanf("%s", databuf);
datalen = strlen(databuf) + 1;
if (sendto(sd, databuf, datalen, 0, (struct sockaddr*) &groupSock,
sizeof(groupSock)) < 0)
datalen = 1024;
memset(databuf, 0x00, sizeof(databuf));
read_size = recvfrom(sd, databuf, datalen, 0,
(struct sockaddr*) &rcv_addr, &rcv_addr_size);
printf("The message from multicast ckient is: \"%s\"\n", databuf);
}
return 0;
}
client.c
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
struct sockaddr_in localSock, rcv_addr;
struct ip_mreq group;
int sd;
int datalen;
char databuf[1024];
int main(int argc, char *argv[]) {
/* Create a datagram socket on which to receive. */
socklen_t rcv_addr_size = sizeof(struct sockaddr_in);
sd = socket(AF_INET, SOCK_DGRAM, 0);
if (sd < 0) {
perror("Opening datagram socket error");
exit(1);
}
else
printf("Opening datagram socket....OK.\n");
{
int reuse = 1;
if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (char*) &reuse,
sizeof(reuse)) < 0) {
perror("Setting SO_REUSEADDR error");
close(sd);
exit(1);
} else
printf("Setting SO_REUSEADDR...OK.\n");
}
memset((char*) &localSock, 0, sizeof(localSock));
localSock.sin_family = AF_INET;
localSock.sin_port = htons(4321);
localSock.sin_addr.s_addr = INADDR_ANY;
if (bind(sd, (struct sockaddr*) &localSock, sizeof(localSock))) {
perror("Binding datagram socket error");
close(sd);
exit(1);
} else
printf("Binding datagram socket...OK.\n");
group.imr_multiaddr.s_addr = inet_addr("226.1.1.1");
group.imr_interface.s_addr = INADDR_ANY;
if (setsockopt(sd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*) &group,
sizeof(group)) < 0) {
perror("Adding multicast group error");
close(sd);
exit(1);
} else
printf("Adding multicast group...OK.\n");
int read_size;
while (1) {
datalen = 1024;
memset(databuf, 0x00, sizeof(databuf));
read_size = recvfrom(sd, databuf, datalen, 0,
(struct sockaddr*) &rcv_addr, &rcv_addr_size);
printf("The message from multicast server is: \"%s\"\n", databuf);
memset(databuf, 0x00, sizeof(databuf));
scanf("%s", databuf);
datalen = strlen(databuf) + 1;
if (sendto(sd, databuf, datalen, 0, (struct sockaddr*) &localSock,
sizeof(localSock)) < 0)
break;
}
return 0;
}
Your server is sending to the wrong address.
The server is using localSock as the destination address for sendto:
if(sendto(sd, databuf, datalen, 0, (struct sockaddr*)&localSock, sizeof(localSock)) < 0)
But you have that address set to 0:
localSock.sin_family = AF_INET;
localSock.sin_port = htons(4321);
localSock.sin_addr.s_addr = INADDR_ANY;
You want to instead use rcv_addr, which was populated as the source address from recvfrom. Using this address as the destination will send the response back where it came from:
if(sendto(sd, databuf, datalen, 0, (struct sockaddr*)&rcv_addr, sizeof(rcv_addr)) < 0)
Multicast connection is like broadcast communication, you send the packet to a forum of receivers, awaiting to read it, and they consume it (if it arrives). This normally means that you have to arrange for bidirectional connection in a way that allows all people skeaking in a room and selecting yourself the responses, as everybody is talking to everybody in a multicast channel. Imagine you are chatting in a IRC channel, and you have to arrange with somebody how to direct messages only to that person, but with the anarchy of anybody being able to respond to such messages in the way they want. You have always to think that what you say, you say to everybody susbscribed in that multicast channel, so normally you will receive several response packets, from which you will have to select...

Bind error in IPv6 server

I'm trying make IPv6 server, but i have issue with socket binding.
"could not bind socket"
All code:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdbool.h>
int main(int argc, char *argv[]) {
int server_port = 8877;
struct sockaddr_in6 server_address;
memset(&server_address, 0, sizeof(server_address));
server_address.sin6_family = AF_INET6;
server_address.sin6_port = htons(server_port);
server_address.sin6_addr = in6addr_any;
int sockfd;
if (sockfd = socket(AF_INET6, SOCK_STREAM, 0) < 0) {
printf("could not create listen socket\n");
return 1;
}
if (bind(sockfd, (struct sockaddr *)&server_address, sizeof(server_address)) < 0) {
printf("could not bind socket\n");
return 1;
}
int numberOfClients = 1;
if (listen(sockfd, numberOfClients) < 0) {
printf("could not open socket for listening\n");
return 1;
}
struct sockaddr_in client_address;
int client_len = 0;
char buff4[INET_ADDRSTRLEN];
while (1) {
int sock;
if ((sock =
accept(sock, (struct sockaddr *)&client_address,
0)) < 0) {
printf("could not open a socket to accept data\n");
return 1;
}
//printf("client connected with ip address: %s\n", inet_ntop(AF_INET, &(client_address.sin_addr), buff4, INET_ADDRSTRLEN));
int n = 0;
int len = 0, maxlen = 100;
char buffer[maxlen];
char *pbuffer = buffer;
printf("client connected with ip address: %s\n",
inet_ntoa(client_address.sin_addr));
while ((n = recv(sock, pbuffer, maxlen, 0)) > 0) {
pbuffer += n;
maxlen -= n;
len += n;
printf("received: '%s'\n", buffer);
// echo received content back
send(sock, buffer, len, 0);
}
close(sock);
}
close(sockfd);
return 0;
}
The problem here is your order of operations.
You have written:
if (sockfd = socket(AF_INET6, SOCK_STREAM, 0) < 0) {
You expected this to assign the return value of socket() to sockfd. But instead, it compares that return value to 0, and whether that value is less than 0 is what is actually stored in sockfd.
Before comparing, you should use an extra pair of parentheses to make explicit that you want to do the assignment and only then do the comparison:
if ((sockfd = socket(AF_INET6, SOCK_STREAM, 0)) < 0) {
Better yet, make the code more maintainable by making it more obvious what is going on, by assigning first and then comparing separately.
sockfd = socket(AF_INET6, SOCK_STREAM, 0);
if (sockfd < 0) {

C Server - Print Received Massage?

I send this C Server a message w/ netcat.
echo <message> | nc <ip> <port>
it prints:
Client IP : <ip>
I want it to also print:
Client Message : <message>
C SERVER
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <err.h>
char response[] = "hi";
int main()
{
int one = 1, client_fd;
struct sockaddr_in svr_addr, cli_addr;
socklen_t sin_len = sizeof(cli_addr);
int sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0)
err(1, "can't open socket");
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(int));
int port = 85;
svr_addr.sin_family = AF_INET;
svr_addr.sin_addr.s_addr = INADDR_ANY;
svr_addr.sin_port = htons(port);
if (bind(sock, (struct sockaddr *) &svr_addr, sizeof(svr_addr)) == -1) {
close(sock);
err(1, "Can't bind");
}
listen(sock, 5);
while (1) {
client_fd = accept(sock, (struct sockaddr *) &cli_addr, &sin_len);
printf("Client IP : [%s]\n", inet_ntoa(cli_addr.sin_addr));
if (client_fd == -1) {
perror("Can't accept");
continue;
}
write(client_fd, response, sizeof(response) - 1); /*-1:'\0'*/
close(client_fd);
}
}
You just have to read data from the socket (after the accept call, once you've checked that client_fd is usable):
if (client_fd == -1) {
perror("Can't accept");
continue;
}
printf("Client Message : <");
/* buffer to store result */
char buffer[64] = "";
/* while we can read from socket */
while (read(client_fd, buffer, sizeof buffer-1) > 0)
{
/* write what have been read */
printf("%s", buffer);
}
puts(">");
write(client_fd, response, sizeof(response) - 1); /*-1:'\0'*/
close(client_fd);
You could also use recv function.

connect() function taking too long

When I type in to the terminal:
echo "GET /" | ./<executable name> www.google.com <port number, usually 80>
the terminal just sits there like it's waiting for input or it's stuck in an infinite loop. What is happening is that connection is taking too long I think.
/*Creating socket*/
int sock = socket(AF_INET,SOCK_STREAM, IPPROTO_TCP);
if (sock < 0) {
printf("error creating socket\n");
exit(1);
}
printf("1\n");
/*Establish connection to the echo server*/
int r = connect(sock, addrList->ai_addr, addrList->ai_addrlen);
printf("1.5\n");
if (r < 0) {
perror("Connection failed\n");
exit(1);
}
printf("2\n");
Here, the 1 prints out, but the 1.5 right after the connect doesn't print out and the terminal just sits.
This problem didn't happen before and I used to get the page's source code back instantly. But now this problem is occurring.
It started occurring after I typed in to the terminal: netstat -an -A inet | grep :2525
so this may have had an effect.
Here is the entire code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
int main(int argc, char *argv[]) {
if (argc != 3) {
printf("Invalid arguments\n");
exit(1);
}
char *serverIP = argv[1]; /*Server hostname*/
char *portNumber = argv[2]; /*Port Number*/
void *numericAddress;
char addrBuffer[INET6_ADDRSTRLEN];
in_port_t port;
char buffer_stdin[65535];
char buffer_stdout[65535];
int bytes_read = 0;
int bytes_written = 0;
/*getting integral number of string representation of port number*/
in_port_t servPort = atoi(argv[2]);
/*------------------get binary number of hostname-----------------*/
struct addrinfo addrCriteria;
memset(&addrCriteria, 0, sizeof(addrCriteria));
addrCriteria.ai_family = AF_INET;
addrCriteria.ai_socktype = SOCK_STREAM;
addrCriteria.ai_protocol = IPPROTO_TCP;
struct addrinfo *addrList;
int rtnVal = getaddrinfo(serverIP, portNumber, &addrCriteria, &addrList);
if (rtnVal != 0) {
printf("getaddrinfo() failed\n");
exit(1);
}
numericAddress = &((struct sockaddr_in *) (addrList->ai_addr))->sin_addr;
/*Converting port to binary*/
((struct sockaddr_in *)(addrList->ai_addr))->sin_port = htonl(servPort);
/*----------------------------------------------------------------*/
inet_ntop(addrList->ai_addr->sa_family, numericAddress, addrBuffer, sizeof(addrBuffer));
printf("IP ADDRESS: %s\n", addrBuffer);
/*Creating socket*/
int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock < 0) {
printf("error creating socket\n");
exit(1);
}
/*printf("1\n");*/
/*Establish connection to the echo server*/
int r = connect(sock, addrList->ai_addr, addrList->ai_addrlen);
printf("%d\n", r);
if (r < 0) {
perror("Connection failed\n");
exit(1);
}
printf("2\n");
/*Reading from stdin and writing to socket until stdin ends
bytes_read = read(0, buffer_stdin, sizeof(buffer_stdin));
write(sock, buffer_stdin, bytes_read);*/
while ((bytes_read = read(0, buffer_stdin, sizeof(buffer_stdin)-1)) > 0) {
write(sock, buffer_stdin, bytes_read);
}
/*Shutting down write end of socket*/
int r_shutdown = shutdown(sock, SHUT_WR);
if (r_shutdown < 0) {
printf("Shutting down write end of socket failed\n");
exit(1);
}
/*Reading from socket and writing to stdout until socket ends*/
while ((bytes_read = read(sock, buffer_stdout, sizeof(buffer_stdout)-1)) > 0) {
write(1, buffer_stdout, bytes_read);
}
close(sock);
exit(0);
}
The correct way to do it is :
struct sockaddr_in address;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd!=-1)
{
perror("socket :");
printf("sockfd = %d\n", sockfd);
}
else
{
perror("socket");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = inet_addr("127.0.0.1");
address.sin_port = htons(9734);
len = sizeof(struct sockaddr_in);
result = connect(sockfd, (struct sockaddr *)&address, len);
Nvm I figured it out.
Apparently I had to take into account big endian vs little endian, and so in this line:
((struct sockaddr_in *)(addrList->ai_addr))->sin_port = htonl(servPort);
the htonl should've been htons, so:
((struct sockaddr_in *)(addrList->ai_addr))->sin_port = htons(servPort);

Resources