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&auml;t f&uuml;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&auml;t f&uuml;r Elektro- und Informationstechnik</h1>
<p>Herzlich Willkommen im &ouml;ffentlich zug&auml;nglichen Teil des Intranets der Fakult&auml;t f&uuml;r Elektro- und Informationstechnik (EIT).</p>
<h2>&Ouml;ffentliche Webseiten im Intranet</h2>
<p>Folgende Webseiten sind ohne Authentifizierung aufrufbar. Sie sind auch von au&szlig;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&auml;nkte Webseiten im Intranet</h2>
<p>F&uuml;r Angeh&ouml;rige der Hochschule stehen im Intranet Seiten mit Zugangsbeschr&auml;nkung zur Verf&uuml;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&uuml;r  Studierende der Fakult&auml;t EIT sind auch f&uuml;r alle anderen Fakult&auml;tsangeh&ouml;rige  zug&auml;nglich. Der Aufruf dieser Seiten ist auch aus dem Internet m&ouml;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&auml;t EIT beschr&auml;nkt. Aufgrund der verschl&uuml;sselten Verbindung  sind diese Seiten nur innerhalb der Hochschule oder &uuml;ber  ***-Verbindung erreichbar. F&uuml;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">
&nbsp;</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 &Auml;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照片请求的主要内容,如果未能解决你的问题,请参考以下文章

C语言socket网络编程

Python 网络编程和Socket

网络编程socke

网络编程基础day08:socke编程入门

socket编程python+c

socket