-
Star
(120)
You must be signed in to star a gist -
Fork
(29)
You must be signed in to fork a gist
-
-
Save nolim1t/126991 to your computer and use it in GitHub Desktop.
#include <stdio.h> | |
#include <string.h> | |
#include <stdlib.h> | |
#include <unistd.h> | |
#include <fcntl.h> | |
#include <netinet/tcp.h> | |
#include <sys/socket.h> | |
#include <sys/types.h> | |
#include <netinet/in.h> | |
#include <netdb.h> | |
int socket_connect(char *host, in_port_t port){ | |
struct hostent *hp; | |
struct sockaddr_in addr; | |
int on = 1, sock; | |
if((hp = gethostbyname(host)) == NULL){ | |
herror("gethostbyname"); | |
exit(1); | |
} | |
bcopy(hp->h_addr, &addr.sin_addr, hp->h_length); | |
addr.sin_port = htons(port); | |
addr.sin_family = AF_INET; | |
sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); | |
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (const char *)&on, sizeof(int)); | |
if(sock == -1){ | |
perror("setsockopt"); | |
exit(1); | |
} | |
if(connect(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) == -1){ | |
perror("connect"); | |
exit(1); | |
} | |
return sock; | |
} | |
#define BUFFER_SIZE 1024 | |
int main(int argc, char *argv[]){ | |
int fd; | |
char buffer[BUFFER_SIZE]; | |
if(argc < 3){ | |
fprintf(stderr, "Usage: %s <hostname> <port>\n", argv[0]); | |
exit(1); | |
} | |
fd = socket_connect(argv[1], atoi(argv[2])); | |
write(fd, "GET /\r\n", strlen("GET /\r\n")); // write(fd, char[]*, len); | |
bzero(buffer, BUFFER_SIZE); | |
while(read(fd, buffer, BUFFER_SIZE - 1) != 0){ | |
fprintf(stderr, "%s", buffer); | |
bzero(buffer, BUFFER_SIZE); | |
} | |
shutdown(fd, SHUT_RDWR); | |
close(fd); | |
return 0; | |
} |
gcc socket.c -o soc
./soc https://www.google.com 80
I tried to call localhost:8080/services from this. It fails in every way. Can you please help me?
@dimuthnc change the code to give 127.0.0.1 for whenever host is localhost
why use PF_INET for create sock.. addr structure be set by AF_INET..
@sebitoelcheater and @dimuthnc you need to modify the request header https://gist.github.com/nolim1t/126991#file-socket-c-L53 to something such as GET /something HTTP/1.1\r\n
, maybe create a #define
if you want to use it everytime OR change the code so it accept a third argument (or parse it from the complete URI): the suffix URI - the requested page.
The GET /\r\n
in this Gist will ask for the index page (/
) if any.
Reminder: a minimal header may look like:
GET /something HTTP/1.1\r\n
Host: www.42.fr\r\n
\r\n
which, if successfully sent, will trigger a request to a web server located at www.42.fr
to get the /something
page using the GET
HTTP method. Note the double \r\n
line ending, ending the header.
I hope this will help you!
Happy coding everyone
I've used your code to get a text file ( about 70KB)
It run through the while loop about 25 times,
but the last loop it seem very slow , I think it's been blocking somewhere ( maybe in read function). please help me to explain .
example the file :
http://super-pomoyka.us.to//trash/ttv-list/ttv.m3u
Hello, i try to run this code on the Star Wars API (https://swapi.co/) but it doesn't work. I've tried multiple configurations :
./api swapi.co/ 80
gethostbyname: Unknown host
./api http://swapi.co/api/people/1/ 80
gethostbyname: Unknown host
Even with you example with google.com, i've got the same error message. Do you know why ?
@RossignolVincent Have you tried www.swapi.co?
what if the response is 302 redirection,
how to make a request to new location?
Thank for this. I used this in conjuction with Arduino Json to get the local weather from http://openweathermap.org. Works like a treat 👍
gethostbyname() isn't very futureproof. gethostbyname2() will at least let you opt for ipv4 or ipv6
As alr-lab pointed out the headers are incomplete.
I think most of the problems people are experiencing is down to not understanding the code (i.e. including the http and ending slash rather than just www.google.com) so it may have been nicer to include some examples or comments. Of course this is 8 years old too so understandably it may not hold up as well now.
It is a good pointer in the right direction but learners will need to work on it bit.
When I try to get this url "http://www.cplusplus.com/" the webserver performs a 301 redirection to the same url.
Why? What am I doing wrong?
This is the command line I am executing:
./a.out www.cplusplus.com 80
Thanks a lot!
Hi everyone!
I found the solution, the get request should be like this :
"GET / HTTP/1.0\r\nHost: www.cplusplus.com\r\n\r\n\r\n"
All the best!
It looks like the GET request is missing a second \r\n. HTTP Requests require a blank line at the end. If you do a raw nc to a web server, and send "GET /" and press enter, you wont get a response. Once hitting enter again, however, you will get a response. This is due to that second \r\n being needed. write(fd, "GET /\r\n", strlen("GET /\r\n")); // write(fd, char[], len); should actually be write(fd, "GET /\r\n\r\n", strlen("GET /\r\n\r\n")); // write(fd, char[], len);
This doesn't work on Mac. I keep getting an error:
Undefined symbols for architecture x86_64:
"_copy", referenced from:
_socket_connect in msgario-a206e2.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
This code snippet should use bcopy()
instead of copy().
copy()
doesn't work.
try with -> ./soc www.google.com 80
Hi;
I am trying to send a Telegram message using HTTP GET. However, I don't know how to pass the required parameters. I have try this:
"GET / HTTP/1.1\r\nHost: https://api.telegram.org/botmybottokenhere/sendMessage?chat_id=mychatidhere&text=mymessagehere\r\nConnection: close\r\n\r\n"
but does not work. I get a 400 bad request error. But if I copy that url and paste it in Chrome the message is sent, so the url is correct. It also works in Python3.7.
Thanks.
I am trying to send a Telegram message using HTTP GET. However, I don't know how to pass the required parameters. I have try this:
"GET / HTTP/1.1\r\nHost: https://api.telegram.org/botmybottokenhere/sendMessage?chat_id=mychatidhere&text=mymessagehere\r\nConnection: close\r\n\r\n"
but does not work. I get a 400 bad request error. But if I copy that url and paste it in Chrome the message is sent, so the url is correct. It also works in Python3.7.
You're getting the 400 error because you are sending an HTTP request to an HTTPS-encrypted endpoint. For what it's worth, I stumbled upon your comment because I am running into this exact same issue and I am trying to figure out how to send an HTTPS-based request using the low-level socket_*() functions. If I figure this out then I'll try to pop back in here and see if I can share my knowledge.
The response I receive in my own attempts are as follows:
400 The plain HTTP request was sent to HTTPS port
400 Bad Request
The plain HTTP request was sent to HTTPS port
This bit of code only relates to non-SSL secured endpoints. For SSL you would have to add in SSL/TLS related negotiation code too.
i have same error like Cannedfood's.
what is the solution? please...
./soc https://www.cplusplus.com 80
I am trying to send a Telegram message using HTTP GET. However, I don't know how to pass the required parameters. I have try this:
"GET / HTTP/1.1\r\nHost: https://api.telegram.org/botmybottokenhere/sendMessage?chat_id=mychatidhere&text=mymessagehere\r\nConnection: close\r\n\r\n"
but does not work. I get a 400 bad request error. But if I copy that url and paste it in Chrome the message is sent, so the url is correct. It also works in Python3.7.You're getting the 400 error because you are sending an HTTP request to an HTTPS-encrypted endpoint. For what it's worth, I stumbled upon your comment because I am running into this exact same issue and I am trying to figure out how to send an HTTPS-based request using the low-level socket_*() functions. If I figure this out then I'll try to pop back in here and see if I can share my knowledge.
The response I receive in my own attempts are as follows:
400 The plain HTTP request was sent to HTTPS port
400 Bad Request
The plain HTTP request was sent to HTTPS port
I think you need to add something like this to add TLS :
int client_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TLS_1_2);
enum {
NONE = 0,
OPTIONAL = 1,
REQUIRED = 2,
};
int verify = OPTIONAL;
err = setsockopt(client_fd, SOL_TLS, TLS_PEER_VERIFY, &verify, sizeof(verify));
Error - IPPROTO_TLS_1_2 is not defined..........
@Andermutu it has been a while , but in case you're still interested :)
This is not valid HTTP:
"GET / HTTP/1.1\r\nHost: [https://api.telegram.org/botmybottokenhere/sendMessage?chat_id=mychatidhere&text=mymessagehere\r\nConnection](https://api.telegram.org/botmybottokenhere/sendMessage?chat_id=mychatidhere&text=mymessagehere%5Cr%5CnConnection): close\r\n\r\n"
The host
header should contain only the host. You've given it a full URL!
And your request path is just /
so it would never work.
Also, you're trying to send a https
request which means the socket needs to be encrypted. And notice that the protocol doesn't go in the HTTP request itself as that refers to the transport being used.
So, your request should look like this (\r\n
replaced with simple new-lines for readability, you still need them in a real request):
GET /botmybottokenhere/sendMessage?chat_id=mychatidhere&text=mymessagehere HTTP/1.1
Host: api.telegram.org
Connection: close
localhost:8080/services
write(fd, "GET /services HTTP/1.1\r\n\r\n", strlen("GET /services HTTP/1.1\r\n\r\n"));
Run command:
gcc socket.c -o socket
./socket localhost 8080
You may want to use bcopy
instead of copy
at line 22
nice work! how can I go to for example, localhost:3000/something ?