C语言socket编程中的HTTP照片请求
Posted
技术标签:
【中文标题】C语言socket编程中的HTTP照片请求【英文标题】:HTTP photo request in socket programming in C language 【发布时间】:2018-04-03 14:43:51 【问题描述】:我正在用 C 语言编写一个 HTTP 客户端请求,以从服务器请求一张照片并将其查看为已编码,然后我将去掉 HTTP 标头并将其保存以将其作为照片查看器打开以将其视为照片。
问题是,当我使用指向该照片的直接链接请求照片时,响应是 html 文本而不是编码的照片(例如当您使用文本编辑器打开照片时)有办法告诉程序我想请求照片内容类型?
我的代码是:
#ifdef _WIN32
#include <windows.h>
#include <winsock.h>
#else // Hier folgen die Ersetzungen f�r die BSD-socks.
#include <stddef.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/un.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define SOCKADDR_IN struct sockaddr_in
#define SOCKADDR struct sockaddr
#define HOSTENT struct hostent
#define SOCKET int
int WSAGetLastError() return errno;
int closesocket(int s) return close(s);
#endif
#include <stdio.h>
#include <stdlib.h>
void perr_exit(char* msg, int ret_code)
printf("%s, Error: ",msg);
printf("%d\n",ret_code);
exit(ret_code);
int main(int argc, char** argv)
char* site;
char* host;
char url[1024];
char send_buf[256];
char recv_buf[256];
long rc;
SOCKET s;
SOCKADDR_IN addr;
#ifdef _WIN32
WSADATA wsa;
#endif
HOSTENT* hent;
// Bevor man anfangen kann, muss man diese WSAStartup Funktion aufrufen.
// Initialisiert TCPIP-Stack.
#ifdef _WIN32
if(WSAStartup(MAKEWORD(2,0),&wsa))
perr_exit("WSAStartup failed",WSAGetLastError());
#endif
addr.sin_family=AF_INET;
addr.sin_port=htons(80);
printf("\nURL: ");
scanf("%s",url);
if(strncmp("http://",url,7)==0)
host=url+7;
else
host=url;
if((site=strchr(host,'/'))!=0)
*site++='\0';
else
site=host+strlen(host); /* \0 */
printf("Host: %s\n",host);
printf("Site: %s\n",site);
printf("Connecting....\n");
if((addr.sin_addr.s_addr=inet_addr(host))==INADDR_NONE)
if(!(hent=gethostbyname(host)))
perr_exit("Cannot resolve Host",WSAGetLastError());
strncpy((char*)&addr.sin_addr.s_addr,hent->h_addr,4);
if(addr.sin_addr.s_addr==INADDR_NONE)
perr_exit("Cannot resolve Host",WSAGetLastError());
s=socket(AF_INET,SOCK_STREAM,0);
#ifdef _WIN32
if (s==INVALID_SOCKET)
#else
if (s<0)
#endif
perr_exit("Cannot create Socket",WSAGetLastError());
if( connect(s,(SOCKADDR*)&addr,sizeof(SOCKADDR)))
perr_exit("Cannot connect",WSAGetLastError());
printf("Connected to %s...\n",host);
sprintf(send_buf,"GET / HTTP/1.0\nUser-Agent: xxxyyy\n\n",site);
printf("Command sent to server: \n%s\n",send_buf);
if((send(s,send_buf,strlen(send_buf),0))<strlen(send_buf))
perr_exit("Cannot send Data",WSAGetLastError());
printf("----Result----\n");
while((rc=recv(s,recv_buf,255,0))>0)
recv_buf[rc]='\0';
printf("%s",recv_buf);
//
printf("\nDONE!");
closesocket(s);
return 0;
回复是:
URL: http://www.eit.hs-karlsruhe.de/bildergalerie/images/fotos.png
Host: www.eit.hs-karlsruhe.de
Site: bildergalerie/images/fotos.png
Connecting....
Connected to www.eit.hs-karlsruhe.de...
Command sent to server:
GET / HTTP/1.0
User-Agent: xxxyyy
----Result----
HTTP/1.1 200 OK
Date: Tue, 03 Apr 2018 14:15:29 GMT
Server: Apache/2.4.10 (Linux/SUSE)
Last-Modified: Wed, 23 Nov 2016 14:45:52 GMT
ETag: "18e1-541f8f20caf37"
Accept-Ranges: bytes
Content-Length: 6369
Content-Type: text/html
Connection: close
<?xml version="1.0" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="content-type" content="application/xhtml+xml;charset=UTF-8"/>
<meta name="Author" content="Tristan Gantner"/>
<meta name="description" content="EIT|EIT Intranet"/>
<title>EIT|EIT Intranet</title>
<link rel="stylesheet" type="text/css" href="/eit-def-css/eit.css"/>
<!--[if lte IE 7]>
<link href="/eit-def-css/patches/patch_3col_fullpage.css" rel="stylesheet" type="text/css" />
<![endif]-->
<!--[if lte IE 6]>
<script src="/eit-def-js/minmax.js" type="text/javascript" />
<![endif]-->
<link rel="shortcut icon" href="/eit-def-ico/eit.ico"/>
<script src="/eit-def-js/eit.js" type="text/javascript"></script>
<script src="/eit-def-js/pan.js" type="text/javascript"></script>
<script src="/eit-def-js/prototype.js" type="text/javascript"></script>
<script src="/eit-def-js/protoplus.js" type="text/javascript"></script>
<script src="/eit-def-js/scriptaculous.js" type="text/javascript"></script>
<script src="/eit-def-js/stdext.js" type="text/javascript"></script>
<script src="/eit-def-js/xmlqry.js" type="text/javascript"></script>
<script src="/eit-def-js/viewport.js" type="text/javascript"></script>
<script type="text/javascript">
<!--- Hide script from browsers that don't understand JavaScript
document.observe('dom:loaded', function()
eitInit();
);
// End hiding -->
</script>
</head>
<body>
<!-- Start: header -->
<div id="header">
<!-- Start: page_margins -->
<div class="page_margins">
<!-- Start: page -->
<div class="page">
<!-- Start: topnav -->
<div id="topnav">
<!-- start: skip link navigation -->
<a href="#navigation_anchor" class="skip" title="skip link">Springe zur Navigation</a>
<span class="hideme">.</span>
<a href="#content_anchor" class="skip" title="skip link">Springe zum Inhalt</a>
<span class="hideme">.</span>
<!-- end: skip link navigation -->
<span>Gast | <a href="#">Kontakt</a> | <a href="#">Impressum</a></span>
</div>
<!-- End: topnav -->
<!-- Start: topline -->
<div id="header_logo">
<a href="http://www.hs-karlsruhe.de"><img src="/eit-def-img/logos/hskalogo.png" border="0" /></a>
</div>
<div id="header_title">
<h1>Fakultät für Elektro- und Informationstechnik</h1>
<h2>Intranet -Server</h2>
</div>
<!-- End: topline -->
</div>
<!-- End: page -->
</div>
<!-- End: page_margins -->
</div>
<!-- End: header -->
<!-- Start: nav -->
<div id="nav">
<!-- Start: page_margins -->
<div class="page_margins">
<!-- Start: page -->
<div class="page">
<a id="navigation_anchor"></a>
<h1 class="hideme">Navigation</h1>
<h2 class="hideme">Bereiche</h2>
<div class="hlist">
<ul >
<li class="active"><strong>Intranet</strong></li>
<li><a href="http://www.eit.hs-karlsruhe.de/eit-pub-cgi/home.cgi">Studenten</a></li>
<li><a href="https://www.eit.hs-karlsruhe.de/eit-sec-cgi/home.cgi">Mitarbeiter</a></li>
<li><a href="http://www.eit.hs-karlsruhe.de/wetter">Wetter</a></li>
<li><a href="http://www.eit.hs-karlsruhe.de/inselnetz">Inselnetz</a></li>
</ul>
</div>
</div>
<!-- End: page -->
</div>
<!-- End: page_margins -->
</div>
<!-- End: nav -->
<!-- Start: main -->
<div id="main">
<!-- Start: page_margins -->
<div class="page_margins">
<!-- Start: page -->
<div class="page">
<!-- Start: col1 -->
<div id="col1">
<div id="col1_content" class="clearfix">
<h2 class="hideme">Seiten im Bereich EIT Intranet</h2>
<ul class="vlist">
<li><span>Intranet</span><ul>
<li><a href="http://www.eit.hs-karlsruhe.de/rss/">Aktuelle Meldungen</a>
</li>
<li><a href="http://www.eit.hs-karlsruhe.de/mathe/">Lernzentrum Mathematik</a></li>
<li><a href="http://www.eit.hs-karlsruhe.de/bildergalerie/">Bildergalerie</a></li>
</ul>
</li>
</ul>
</div>
<!-- End: col1_content -->
</div>
<!-- End: col1 -->
<!-- Start: col3 -->
<div id="col3">
<div id="col3_content" class="clearfix">
<a id="content_anchor"></a>
<h1 class="hideme">Inhalt</h1>
<h1>Intranet der Fakultät für Elektro- und Informationstechnik</h1>
<p>Herzlich Willkommen im öffentlich zugänglichen Teil des Intranets der Fakultät für Elektro- und Informationstechnik (EIT).</p>
<h2>Öffentliche Webseiten im Intranet</h2>
<p>Folgende Webseiten sind ohne Authentifizierung aufrufbar. Sie sind auch von außerhalb der Hochschule erreichbar:</p>
<ul>
<li><a href="http://www.eit.hs-karlsruhe.de/rss/">Aktuelle Meldungen</a></li>
<li><a href="http://www.eit.hs-karlsruhe.de/mathe/">Lernzentrum Mathematik</a></li>
<li><a href="http://www.eit.hs-karlsruhe.de/bildergalerie/">Bildergalerie</a></li>
</ul>
<h2>Zugangsbeschränkte Webseiten im Intranet</h2>
<p>Für Angehörige der Hochschule stehen im Intranet Seiten mit Zugangsbeschränkung zur Verfügung. Benutzername und Passwort entsprechen dem Login des Informationszentrums.</p>
<ul>
<li><strong><a href="http://www.eit.HS-Karlsruhe.DE/eit-pub-cgi/home.cgi">Studentischer Bereich</a></strong>: Die Seiten für Studierende der Fakultät EIT sind auch für alle anderen Fakultätsangehörige zugänglich. Der Aufruf dieser Seiten ist auch aus dem Internet möglich.</li>
<li><strong><a href="https://www.eit.HS-Karlsruhe.DE/eit-sec-cgi/home.cgi">Mitarbeiterbereich</a></strong>: Der Zugang zu diesen Seiten ist auf Mitarbeiter der Fakultät EIT beschränkt. Aufgrund der verschlüsselten Verbindung sind diese Seiten nur innerhalb der Hochschule oder über ***-Verbindung erreichbar. Für einen erfolgreichen Aufruf sollten sie das angebotene Zertifikat zum Aufbau einer gesicherten Verbindung mit ihrem Webbrowser akzeptieren.</li>
</ul>
</div>
<!-- End: col3_content -->
<div id="ie_clearing">
</div>
<!-- End: IE Column Clearing -->
</div>
<!-- End: col3 -->
</div>
<!-- End: page -->
</div>
<!-- End: page_margins -->
</div>
<!-- End: main -->
<!-- Start: footer -->
<div id="footer">
<!-- Start: page_margins -->
<div class="page_margins">
<!-- Start: page -->
<div class="page">
<div id="footer_content">
Layout basiert auf <a href="http://www.yaml.de/">YAML</a>
</div>
<div id="footer_clock">
<a href="#">Impressum</a> | letzte Änderung: Donnerstag, 08.03.2012
</div>
</div>
<!-- End: page -->
</div>
<!-- End: page_margins -->
</div>
<!-- End: footer -->
</body>
</html>
DONE!
我在这里缺少什么?
【问题讨论】:
【参考方案1】:您的GET
请求根本不是在请求实际照片。您正在请求/
,这是www.eit.hs-karlsruhe.de
的根页面。您需要改为请求/bildergalerie/images/fotos.png
。
事实上,您甚至没有请求用户输入的 URL。您只是提取 URL 的域部分,连接到它,然后为该域请求 /
。您应该请求用户输入的完整 URL。
另外,HTTP 需要 \r\n
来换行,而不是 \n
。
另外,send()
可以发送比请求更少的字节。您必须循环调用它,直到发送完所有字节。
试试类似的方法:
#ifdef _WIN32
#include <windows.h>
#include <winsock.h>
#else // Hier folgen die Ersetzungen f�r die BSD-socks.
#include <stddef.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/un.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define SOCKADDR_IN struct sockaddr_in
#define SOCKADDR struct sockaddr
#define HOSTENT struct hostent
#define SOCKET int
int WSAGetLastError() return errno;
int closesocket(int s) return close(s);
#endif
#include <stdio.h>
#include <stdlib.h>
void perr_exit(char* msg, int ret_code = 0)
printf("%s", msg);
if (ret_code)
printf(", Error: %d", ret_code);
printf("\n");
exit(ret_code);
int sendAll(SOCKET s, void *buf, int buflen)
char *pbuf = (char*) buf;
while (buflen > 0)
int sent = send(s, pbuf, buflen, 0);
if (sent < 0) return sent;
pbuf += sent;
buflen -= sent;
return 0;
int main(int argc, char** argv)
char url[1024];
char send_buf[1024+256];
char recv_buf[256];
char* host;
char* resource;
long rc;
SOCKET s;
SOCKADDR_IN addr;
HOSTENT* hent;
#ifdef _WIN32
WSADATA wsa;
#endif
// Bevor man anfangen kann, muss man diese WSAStartup Funktion aufrufen.
// Initialisiert TCPIP-Stack.
#ifdef _WIN32
rc = WSAStartup(MAKEWORD(2,0), &wsa);
if (rc)
perr_exit("WSAStartup failed", rc);
#endif
printf("\nURL: ");
if (scanf("%1023s", url) != 1)
perr_exit("Cannot read input");
if (strncmp("http://", url, 7) != 0)
perr_exit("Enter a valid HTTP url");
host = url + 7;
resource = strchr(host, '/')
if (resource)
*resource++ = '\0';
else
resource = host + strlen(host);
printf("Host: %s\n", host);
printf("Resource: /%s\n", resource);
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(host);
addr.sin_port = htons(80);
if (addr.sin_addr.s_addr == INADDR_NONE)
hent = gethostbyname(host);
if (!hent)
perr_exit("Cannot resolve Host", WSAGetLastError());
if (hent->h_addrtype != AF_INET)
perr_exit("Host did not resolve to IPv4 address");
memcpy(&addr.sin_addr, hent->h_addr, 4);
s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
#ifdef _WIN32
if (s == INVALID_SOCKET)
#else
if (s < 0)
#endif
perr_exit("Cannot create Socket", WSAGetLastError());
printf("Connecting...\n");
if (connect(s, (SOCKADDR*)&addr, sizeof(addr)) != 0)
perr_exit("Cannot connect", WSAGetLastError());
printf("Connected\n");
printf("Sending command to server...\n");
sprintf(send_buf, "GET /%s HTTP/1.0\r\nUser-Agent: xxxyyy\r\nConnection: close\r\n\r\n", resource);
printf("%s", send_buf);
if (sendAll(s, send_buf, strlen(send_buf)) != 0)
perr_exit("Cannot send Data", WSAGetLastError());
printf("----Result----\n");
while ((rc = recv(s, recv_buf, sizeof(recv_buf), 0)) > 0)
printf("%.*s", (int)rc, recv_buf);
if (rc < 0)
perr_exit("Cannot read Data", WSAGetLastError());
//
printf("\nDONE!");
closesocket(s);
#ifdef _WIN32
WSACleanup();
#endif
return 0;
【讨论】:
以上是关于C语言socket编程中的HTTP照片请求的主要内容,如果未能解决你的问题,请参考以下文章