I'm trying to make a connection localhost on port 80 and send a simple http get request and simultaneously I run wireshark and look at the headers. Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <pthread.h>
#include <netinet/in.h>
#include <errno.h>
#include <string.h>
int main(int argc, char *argv[])
{
int yes = 1;
char buffer[1024];
int newsockfd, portno, recv_length, sockfd;
socklen_t clilen;
struct sockaddr_in serv_addr, cli_addr;
ssize_t number;
if (sockfd < 0)
error("ERROR opening socket");
bzero((char *) &serv_addr, sizeof(serv_addr));
sockfd = socket(AF_INET, SOCK_STREAM, 0);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = 0;
serv_addr.sin_port = htons(80);
connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr));
if(send(sockfd,
"GET / HTTP/1.1\r\n
Host: localhost\r\n
Connection: Keep-alive\r\n
Cache-Control: max-age=0\r\n
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,;q=0.8\r\n
User-Agent: Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.91 Safari/537.36\r\n
Accept-Encoding: gzip, deflate, sdch\r\n
Accept-Language: en-US,en;q=0.8\r\n\r\n",
strlen("GET / HTTP/1.1\r\n
Host: localhost\r\n
Connection: Keep-alive\r\n
Cache-Control: max-age=0\r\n
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,;q=0.8\r\n
User-Agent: Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.91 Safari/537.36\r\n
Accept-Encoding: gzip, deflate, sdch\r\n
Accept-Language: en-US,en;q=0.8\r\n\r\n"),
0) > 0)
{
printf("GET send from %d\n", sockfd);
}
else
{
printf("Problem in send %s\n", strerror(errno));
}
But when I compile it and run it gives me a lot of erros. here is the image of errros. After this error I changed the send function to this send(sockfd, "GET / HTTP/1.1\r\n Host: localhost\r\n\r\n", strlen("GET / HTTP/1.1\r\n Host: localhost\r\n\r\n") Compilation went ok but the wireshark shows me HTTP/1.0 400 BAD REQUEST (text/html) So I have few questions.
1)What is the difference between send functions that I've used? I mean does it really matter if I send GET / HTTP/1.1\r\n Host: localhost\r\n\r\n or GET / HTTP/1.1\r\n
Host: localhost\r\n
Connection: Keep-alive\r\n
Cache-Control: max-age=0\r\n
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,;q=0.8\r\n
User-Agent: Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.91 Safari/537.36\r\n
Accept-Encoding: gzip, deflate, sdch\r\n
Accept-Language: en-US,en;q=0.8\r\n\r\n
2)How to configure send function to make correct HTTP GET request?
Hope you can help. Thanks.
You have literal newlines inside your string! You need to close and re-open the quotes on each line. For example:
if(send(sockfd,
"GET / HTTP/1.1\r\n"
"Host: localhost\r\n"
"Connection: Keep-alive\r\n"
"Cache-Control: max-age=0\r\n"
...
Related
I've got a simple C socket server listening at localhost:8080 that continuously reads from the client socket until it encounters quit at the end of the message.
I tested this on Chrome (Android) and Firefox (Android). I sent a POST request as follows:
<form
action="http://localhost:8080"
method="POST" >
<input type="hidden" name="MAX_FILE_SIZE" value="100000"/>
Choose a file to upload: <input name="uploadedfile" type="file"/><br/>
<input type="submit" value="Upload File"/>
</form>
On the server side, I could only see that it recieved the request headers. No file data was recieved.
Req from Chrome:
POST / HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Content-Length: 52
Cache-Control: max-age=0
sec-ch-ua: "Not?A_Brand";v="8", "Chromium";v="108", "Google Chrome";v="108"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Linux"
Origin: http://localhost:5000
DNT: 1
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: same-site
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: http://localhost:5000/
Accept-Encoding: gzip, deflate, br
Accept-Language: en-GB,en-US;q=0.9,en;q=0.8,bn;q=0.7
When I added enctype="multipart/form-data" to the above form's attribute though, the full data and file with multiple boundaries was recieved.
Afterwards I tried the following POST with and without multipart:
<form
action="http://localhost:8080"
method="POST" >
<input name="test" value="foobar"/>
<input type="submit" value="Submit"/>
</form>
Results were same, only headers were recieved with urlencoded data. Full data was sent with multipart.
My question is why this is happening, and does the browser expect a response in the first case before it continues sending further data?
My aim is to recieve the POST data at once. Is that not possible?
On a side note, I noticed that after the multipart POST request, the request didn't end with two CR LFs, instead just one.
Edit: Just noticed that when I reload the browser it closes the connection and at that moment the remaining POST data shows up (without any CR LF ending after the POST).
Serve code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <unistd.h>
int main (int argc, char *argv[]) {
int portno = argc == 2 ? atoi(argv[1]) : 8080;
int srvfd = socket(AF_INET, SOCK_STREAM, 0);
int option = 1;
setsockopt(srvfd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option));
struct sockaddr_in serv_addr;
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(srvfd, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) < 0) {
perror("server: error binding");
exit(1);
}
listen(srvfd, 1000);
printf("server: listening at port %d\n\n", portno);
struct sockaddr_in cli_addr;
socklen_t clilen = sizeof(cli_addr);
int clifd = accept(srvfd, (struct sockaddr*) &cli_addr, &clilen);
while (true) {
char buffer[256];
int n = read(clifd, buffer, 255);
if (n == 0) {
fprintf(stderr, "server: error: connection closed\n");
exit(1);
} else if (n < 0) {
perror("server: error reading from socket");
exit(1);
}
buffer[n] = 0;
printf("%s", buffer);
if (!strncmp(buffer, "quit", 4))
exit(0);
}
return 0;
}
After printing some data, call fflush(stdout); to make sure it is not buffered.
There is not an extra CRLF after the end of the POST data. The server knows the end of the POST data because of the Content-Length header. Because the browser specifies Content-Length: 52 the server knows the POST data is exactly 52 bytes.
Here is my code where I tried to make an HTTP request
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
int main(int argc, char* argv[]) {
//create the socket
int network_socket;
network_socket = socket(AF_INET, SOCK_STREAM, 0);
//specify an address for the socket
struct sockaddr_in server_address;
server_address.sin_family = AF_INET;
server_address.sin_port = htons(80);
inet_pton(AF_INET, "208.97.177.124", &server_address.sin_addr);
//connect
int connection_status = connect(network_socket, (struct sockaddr *) &server_address, sizeof(server_address));
if (connection_status == -1) {
printf("There was an error making a connection to the remote socket\n\n");
}
//send information
char message[1024];
strcpy(message , "GET /index.html HTTP/1.1\r\nHost: perdu.com\r\nUser-Agent: Mozilla/4.0 (compatible; MSIE5.01; Windows NT)\r\nAccept-Language: en-us\r\nAccept-Encoding: gzip, deflate\r\nConnection: Keep-Alive\r\n\r\n");
send(network_socket, message, sizeof(message), 0);
//receive information
char server_response[2048];
memset(server_response, '0',sizeof(server_response));
int size = recv(network_socket, &server_response, sizeof(server_response), 0);
//print the size
printf("size is %d\n\n", size);
//print the data
printf("The server sent the response : %s\n", server_response);
//close the socket
close(network_socket);
return 0;
}
The server sent the response :
HTTP/1.1 200 OK
Date: Wed, 25 Mar 2020 14:29:19 GMT
Server: Apache
Upgrade: h2
Connection: Upgrade, Keep-Alive
Last-Modified: Thu, 02 Jun 2016 06:01:08 GMT
ETag: "cc-5344555136fe9-gzip"
Accept-Ranges: bytes
Cache-Control: max-age=600
Expires: Wed, 25 Mar 2020 14:39:19 GMT
Vary: Accept-Encoding,User-Agent
Content-Encoding: gzip
Content-Length: 163
Keep-Alive: timeout=2, max=100
Content-Type: text/html
?
And it ends with a question mark "?" instead of the HTML content. Why ?
I wrote a simple TCP client and server program in C language.
It works fine among them but I have a doubt.
What if I wanted to access the TCP server from the web server?
I got the headers from web server and I can't write() back to the web browser. Should the response be in HTTP specifications compulsorily?
I get the following error:
Server Code:
// Server side C program to demonstrate Socket programming
#include <stdio.h>
#include <sys/socket.h>
#include <unistd.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
#define PORT 8080
int main(int argc, char const *argv[])
{
int server_fd, new_socket; long valread;
struct sockaddr_in address;
int addrlen = sizeof(address);
char buffer[1024] = {0};
char *hello = "Hello from server";
// Creating socket file descriptor
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0)
{
perror("In socket");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons( PORT );
// Forcefully attaching socket to the port 8080
if (bind(server_fd, (struct sockaddr *)&address, sizeof(address))<0)
{
perror("In bind");
exit(EXIT_FAILURE);
}
if (listen(server_fd, 3) < 0)
{
perror("In listen");
exit(EXIT_FAILURE);
}
while(1)
{
if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen))<0)
{
perror("In accept");
exit(EXIT_FAILURE);
}
valread = read( new_socket , buffer, 1024);
printf("%s\n",buffer );
write(new_socket , hello , strlen(hello));
printf("Hello message sent\n");
}
return 0;
}
Output:
GET / HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
DNT: 1
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Hello message sent
What is the problem? Is browser also expecting HTTP type response from the server? As the server is sending plain text, web browser can't display the contents. Is this the reason for the error displayed in web browser?
What is the problem? Is browser also expecting HTTP type response from the server? As the server is sending plain text, web browser can't display the contents. Is this the reason for the error displayed in web browser?
Yes, the browser expects a HTTP response.
Here a simple HTTP response:
HTTP/1.1 200 OK
Content-Type: text/plain
Content-Length: 12
Hello world!
C Code snippet:
const char *hello = "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nContent-Length: 12\r\n\r\nHello world!";
Parts explained:
HTTP/1.1 specifies the HTTP protocol version.
200 OK is the so called response status. 200 means no error.
List of HTTP status codes (wikipedia)
Content-Type and Content-Length are http headers:
Content-Type refers to the content type (who would've guessed?). text/plain means plaintext. (There is also text/html, image/png etc..)
Content-Length total size of the response in bytes.
Hi I'm building a primitive browser in c which is to do a very simple task. I'm trying to get my client to simply readout the response message from a server that I request from. I'm trying to get a simple response from www.yahoo.com. I have experimented with many different request messages which have all sent successfully. The following request messages are below.
GET http://www.yahoo.com HTTP/1.1\r\n
Host: www.yahoo.com:80\r\n
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:7.0.1) Gecko/20100101 Firefox/7.0.1\r\n
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n
Accept-Language: en-us,en;q=0.5\r\n
Accept-Encoding: gzip, deflate\r\n
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n
Connection: keep-alive\r\n
and
GET http://www.yahoo.com HTTP/1.1
Host: www.yahoo.com:80
The problem is that I am not recv()-ing any bytes from the server. recv() however does not result in error being -1. Rather the server just doesn't want to respond. Below is my code.
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#define MAXDATASIZE 500;
int main(int argc, char *argv[]){
struct addrinfo serverSide,*serverInfo;
int mySock, status;
char buf[501],ipstr[INET6_ADDRSTRLEN];
memset(&serverSide, 0, sizeof serverSide);
serverSide.ai_family = AF_UNSPEC;
serverSide.ai_socktype = SOCK_STREAM;
if(getaddrinfo("www.yahoo.com","80",&serverSide,&serverInfo)==0){
printf("get addr success\n");
}
mySock = socket(serverInfo->ai_family, serverInfo->ai_socktype, serverInfo->ai_protocol);
connect(mySock, serverInfo->ai_addr, serverInfo->ai_addrlen);
char msg[500] = "GET / HTTP/1.1\r\n";
strcat(msg," Host: www.yahoo.com:80\r\n");
printf("%s\n",msg);
if((status = send(mySock,msg,strlen(msg),0))== -1){
printf("request not sent %d\n",status);
perror("\n");
}else{
if((status = recv(mySock, buf, 500, 0))== -1){
printf("recieved byte error");
}else{
printf("%s\n Number of bytes recieved %d\n",buf,status);
}
}
close(mySock);
freeaddrinfo(serverInfo);
return 0;
}
Any help would be great. Thanks!
HTTP protocol requires that 2 carriage returns/newlines are sent to end the HTTP request
I dont see them in your question
There must be two newlines after the header: strcat(msg,"Host: www.yahoo.com:80\r\n\r\n");
recv() returns 0 when remote has closed the socket.
Use proper address family AF_INET instead of AF_UNSPEC.
Also check socket() and connect() return values, e.g. (include errno.h, stdlib.h):
if (mySocket == -1) {
perror("Creating socket failed");
exit(EXIT_FAILURE);
}
I have the following raw HTTP request:
GET http://www.google.ie/ HTTP/1.1
Host: www.google.ie
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:5.0) Gecko/20100101 Firefox/5.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encod...
I'm trying to send this from my localhost. Could someone point me in the right direction as to how I might do this in C or C++?
I'm currently looking at sockets, but it's not really working.
int sockfdi, portnoi, ni;
struct sockaddr_in serv_addri;
struct hostent *serveri;
portnoi =80;
sockfdi = socket(AF_INET, SOCK_STREAM, 0);
if (sockfdi < 0){
error("***ERROR opening socket");
}
serveri = gethostbyname("172.16.1.218");
if (serveri == NULL){
fprintf(stderr,"***ERROR, no such host\n");
exit(0);
}
bzero((char *) &serv_addri, sizeof(serv_addri));
serv_addri.sin_family = AF_INET;
bcopy((char *)serveri->h_addr, (char *)&serv_addri.sin_addr.s_addr, serveri->h_length);
serv_addri.sin_port = htons(portnoi);
if (connect(sockfdi,(struct sockaddr *) &serv_addri,sizeof(serv_addri)) < 0){
error("***ERROR connecting");
}
printf("Please enter the message: ");
bzero(buffer,256);
You could try using libcurl instead of sockets:
#include <stdio.h>
#include <curl/curl.h>
int main(void)
{
CURL *curl;
CURLcode res;
struct curl_slist *headers = NULL;
curl = curl_easy_init();
if(curl) {
headers = curl_slist_append(headers, "Host: www.google.ie");
headers = curl_slist_append(headers, "User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:5.0) Gecko/20100101 Firefox/5.0");
headers = curl_slist_append(headers, "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
headers = curl_slist_append(headers, "Accept-Language: en-us,en;q=0.5");
/* Add more headers here */
curl_easy_setopt(curl, CURLOPT_URL, "http://www.google.ie/");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
/* always cleanup */
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
return 0;
}