Skip to content

Commit 11764b1

Browse files
committed
add request.c
1 parent a3c2f2b commit 11764b1

File tree

1 file changed

+277
-0
lines changed

1 file changed

+277
-0
lines changed

c/socket/windows/request.c

Lines changed: 277 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,277 @@
1+
#include <time.h>
2+
#include <stdio.h>
3+
#include <string.h>
4+
#include <WinSock2.h>
5+
// #pragma comment(lib, "ws2_32.lib") //加载 ws2_32.dll
6+
7+
typedef void Fun(char *, int);
8+
9+
#define MAXLINE 100
10+
#define MAXRECV 0xfff
11+
#define PROXY_IP "192.168.10.1"
12+
#define PROXY_PORT 1088
13+
#define PROXY_FLAG 1
14+
15+
FILE *fp = NULL;
16+
_Bool dowm_flag = 0;
17+
18+
const char *format_headers = (
19+
"GET %s HTTP/1.1\r\n"
20+
"Host: %s\r\n"
21+
"Connection: keep-alive\r\n"
22+
"Accept: */*\r\n"
23+
"%s"
24+
"User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36 Edg/101.0.1210.47\r\n\r\n"
25+
);
26+
27+
void get_admin(const char * url, char *admin)
28+
{
29+
int start = 7;
30+
if (strstr(url, "https"))
31+
start++;
32+
char *r1 = strchr(url+start, ':');
33+
char *r2 = strchr(url+start, '/');
34+
int admin_len = r1 ? r1-url-start : r2 ? r2-url-start : strlen(url)-start;
35+
36+
strncpy(admin, url+start, admin_len);
37+
}
38+
39+
void get_admin_ip(const char *url, char *ip)
40+
{
41+
char admin[30] = {0};
42+
get_admin(url, admin);
43+
44+
struct hostent *phst = gethostbyname(admin);
45+
struct in_addr * iddr = (struct in_addr*)phst->h_addr;
46+
inet_ntoa(*iddr);
47+
strcpy(ip, inet_ntoa(*iddr));
48+
}
49+
50+
int get_url_port(const char * url)
51+
{
52+
int port;
53+
char *p;
54+
55+
if (p = strchr(url+7, ':'))
56+
{
57+
sscanf(p+1, "%d", &port);
58+
return port;
59+
}
60+
61+
char *ret = strstr(url, "https");
62+
return ret ? 443 : 80;
63+
}
64+
65+
_Bool get_file_name(char *header, char *filename)
66+
{
67+
char str[200];
68+
char *p;
69+
p = strstr(header, "Content-Disposition");
70+
if (p == NULL) return 0;
71+
sscanf(p, "%*s %[^\n]", str);
72+
p = strchr(str, '\'');
73+
if (p == NULL) return 0;
74+
p += 2;
75+
strncpy(filename, p, strlen(p)-1);
76+
filename[strlen(p)-1] = '\0';
77+
78+
return 1;
79+
}
80+
81+
void check_type(const char *url, char *type, char *filename, int nameflag)
82+
{
83+
char type_list[][15] = {"json", "text", "html", "x-javascript"};
84+
85+
if (type == NULL)
86+
return;
87+
88+
for (int i=0; i<4; i++)
89+
{
90+
if (strstr(type, type_list[i]))
91+
return;
92+
}
93+
94+
if (!nameflag)
95+
{
96+
char *p = strrchr(url, '/') + 1;
97+
char *q = strrchr(p, '?');
98+
if (q)
99+
{
100+
strncpy(filename, p, q-p);
101+
filename[q-p] = '\0';
102+
}
103+
else
104+
{
105+
strncpy(filename, p, strlen(p));
106+
filename[strlen(p)] = '\0';
107+
}
108+
if (strchr(p, '.') == NULL)
109+
{
110+
char ext[10] = {0};
111+
ext[0] = '.';
112+
113+
sscanf(type, "%*[^/]/%[a-zA-Z]", ext+1);
114+
strcat(filename, ext);
115+
}
116+
}
117+
fp = fopen(filename, "wb");
118+
dowm_flag = 1;
119+
}
120+
121+
void request(const char *sUrl, Fun *fun)
122+
{
123+
struct sockaddr_in servaddr;
124+
clock_t start, end;
125+
SOCKET sockfd;
126+
127+
char buf[MAXRECV+1] = {0};
128+
char send_msg[strlen(format_headers) + strlen(sUrl)*2];
129+
char data_type[10] = "text/plain";
130+
char header[2500] = {0};
131+
char admin[30] = {0};
132+
char filename[100];
133+
char ip[20] = {0};
134+
_Bool chunked = 1;
135+
int header_len = 0;
136+
int cont_len = 0;
137+
int data_len = 0;
138+
int status = 0;
139+
int r_len;
140+
int port;
141+
char *p;
142+
char *q;
143+
144+
WSADATA wsaData;
145+
WSAStartup(MAKEWORD(2, 2), &wsaData);
146+
147+
port = get_url_port(sUrl);
148+
get_admin(sUrl, admin);
149+
get_admin_ip(sUrl, ip);
150+
sprintf(send_msg, format_headers, sUrl, admin, \
151+
strstr(admin, "i.pximg.net")?"referer: http://www.pixiv.net/\r\n":""
152+
);
153+
154+
sockfd = socket(AF_INET, SOCK_STREAM, 0);
155+
156+
memset(&servaddr, 0, sizeof(servaddr));
157+
158+
servaddr.sin_family = AF_INET;
159+
servaddr.sin_addr.s_addr = inet_addr(PROXY_FLAG?PROXY_IP:ip);
160+
servaddr.sin_port = htons(PROXY_FLAG?PROXY_PORT:port);
161+
162+
connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
163+
send(sockfd, send_msg, strlen(send_msg), 0);
164+
165+
start = clock();
166+
167+
while (1)
168+
{
169+
memset(buf, 0, sizeof(buf));
170+
r_len = recv(sockfd, buf, MAXBYTE, 0);
171+
memmove(header+header_len, buf, r_len);
172+
header_len += r_len;
173+
p = strstr(header, "\r\n\r\n");
174+
if (p)
175+
{
176+
p[0] = '\0';
177+
p += 4;
178+
data_len = header_len-(p-header);
179+
break;
180+
}
181+
}
182+
183+
sscanf(header, "%*s %d", &status);
184+
if (q = strstr(header, "Content-Type"))
185+
sscanf(q, "%*s %s", data_type);
186+
check_type(sUrl, data_type, filename, get_file_name(header, filename));
187+
188+
// 打印 response
189+
if (status != 200)
190+
printf("\n%s\n\n", header);
191+
fun(p, data_len);
192+
193+
if (strstr(header, "Transfer-Encoding: chunked") == NULL)
194+
{
195+
chunked = 0;
196+
p = strstr(header, "Content-Length");
197+
sscanf(p, "%*s %d", &cont_len);
198+
}
199+
200+
while(1)
201+
{
202+
if (!chunked)
203+
{
204+
if (data_len >= cont_len) break;
205+
}
206+
else
207+
{
208+
if (strstr(buf, "\r\n0\r\n\r\n")) break;
209+
}
210+
r_len = recv(sockfd, buf, MAXRECV, 0);
211+
buf[r_len] = '\0';
212+
data_len += r_len;
213+
fun(buf, r_len);
214+
if (dowm_flag)
215+
{
216+
end = clock();
217+
printf("\r");
218+
printf("downloading %d/%d bytes %.0f%% - %.1fs",\
219+
data_len, cont_len, (data_len/(float)cont_len)*100, (end-start)/1000.0
220+
);
221+
}
222+
}
223+
224+
fclose(fp);
225+
closesocket(sockfd);
226+
WSACleanup();
227+
228+
return;
229+
}
230+
231+
void process_data(char * str, int len)
232+
{
233+
if (!dowm_flag)
234+
{
235+
printf("%s", str);
236+
}
237+
else
238+
{
239+
fwrite(str, sizeof(char), len, fp);
240+
}
241+
}
242+
243+
void https_to_http(char **url)
244+
{
245+
if (url[1][4] == 's')
246+
{
247+
memmove(url[1]+1, "http", 4);
248+
url[1]++;
249+
}
250+
}
251+
252+
int main(int argc, char *argv[])
253+
{
254+
clock_t start, end;
255+
// char *url = "http://tva1.sinaimg.cn/large/ec43126fgy1h1753rj0z3j20k00zk7b7.jpg";
256+
// char *url = "http://api.lolicon.app/setu/v2";
257+
258+
if (argc < 2)
259+
{
260+
printf("usage: ./request url\n");
261+
exit(0);
262+
}
263+
264+
if (argc < 3 || !strstr(argv[2], "-b"))
265+
system("chcp 65001");
266+
267+
https_to_http(argv);
268+
printf("\n");
269+
start = clock();
270+
request(argv[1], process_data);
271+
// request(url, process_data);
272+
end = clock();
273+
274+
printf("\n\nexecution time %f seconds\n", (end - start)/1000.0);
275+
276+
return 0;
277+
}

0 commit comments

Comments
 (0)