billtian 发表于 2015-3-24 20:11:24

C#中的HttpWebRequest底层是如何实现的? yeelink上传图片

用C#写了个小工具软件上传图片到,yeelink.net功能正常,现在需要把这个功能移植到芯片上实现,需要知道SOCKET层的实现细节,了解的朋友指点下,谢谢!
上传代码如下
                HttpWebRequest http = (HttpWebRequest)WebRequest.Create("http://api.yeelink.net/v1.1/device/" + DeviceID.Text + "/sensor/" + SensorID.Text + "/datapoints");

                http.Accept = "application/json";
                http.ContentType = "application/json";
                http.Headers.Add("U-ApiKey", APIKey.Text);
                http.Method = "POST";

                FileStream fs = File.OpenRead(imagefile);
                byte[] image_bytes = ConvertFileToByteBuffer(fs);
                Stream newStream = http.GetRequestStream();
                newStream.Write(image_bytes, 0, image_bytes.Length);
                newStream.Close();
                fs.Close();

                response = http.GetResponse();

                Stream stream = response.GetResponseStream();
                StreamReader sr = new StreamReader(stream);
                String content = sr.ReadToEnd();
                responsetext.Text = content;

                stream.Close();
上传了一幅5346字节大小的图片,抓包工具显示如下

HTTP之前的几个TCP包感觉是在上传图片数据,但是如何拆分的不清楚,1514*3+1020 不等于 5346字节

SkyGz 发表于 2015-3-24 20:25:26

本帖最后由 SkyGz 于 2015-3-24 20:35 编辑

就是TCP协议 连接 主域名,连上后, 发送 HTTP头信息(包含防问的网址URL, 以及COOKIE, 提交的表单参数后),发送完头信息后, 接着提交 文件数据即可

抓包工具,看 ID为 15229,15299 这两个 包 就知道了.

贴上一段 以前 DELPHI写的函数,用于 下载的,其实 你要上传的, 实现方法类似,了解一个方向就知道了


Function TFrmMain.Download(ServerFileName, LocalFileName, ProxyHost, ProxyPort, ProxyUser, ProxyPass: String; IsProxy: Boolean): Boolean;
Var
Header: String;
Buf: Array Of byte;
Rec: Longint;
FF: File;
Cmd: String; //这一行的内容
Reclen, Real_Reclen: Longint; //服务器返回的长度;实际已经收到的长度
Total: Longint; //数据总长
SerAddr: String; //服务器地址
ServerFile: String; //服务器端文件
DownPos: Longint; //上次下载的位置
IsRec: Boolean; //是否可以接收
ServerPort: Integer;
Begin
Try
    result := false;
    IsRec := false;
    IsStop := false;
    //创建保存到本地下载的文件,
    AssignFile(FF, LocalFileName);
    If FileExists(LocalFileName) = true Then
    Begin
      Reset(FF, 1);
      DownPos := FileSize(FF);
    End
    Else
    Begin
      Rewrite(FF, 1);
      DownPos := 0;
    End;
    Seek(FF, DownPos);
    //连接网站服务器
    CS.Active := false;
    If IsProxy Then
    Begin
      CS.Host := GetHost(ProxyHost, ServerPort);
      CS.Port := StrToInt(ProxyPort);
    End
    Else
    Begin
      CS.Host := GetHost(ServerFileName, ServerPort);
      CS.Port := ServerPort;
    End;
    CS.ClientType := ctBlocking;

   //获取访问的 网址, 即下载文件的URL
    SerAddr := GetHost(ServerFileName, ServerPort);
    ServerFile := GetFile(ServerFileName);

    //发送HTTP头信息给服务器,查询待下载文件大文件大小
    CS.Active := true;
    Header := '';
    If IsProxy Then
    Begin
      Header := Header + 'HEAD Http://' + SerAddr + ':' + IntToStr(ServerPort) + '/' + ServerFile + ' HTTP/1.0' + #13#10;
      If ProxyUser <> '' Then Header := Header + 'Proxy-Authorization: Basic ' + Base64EnCodeStr(ProxyUser + ':' + ProxyPass) + #13#10;
    End
    Else Header := Header + 'HEAD /' + ServerFile + ' HTTP/1.1' + #13#10;
    Header := Header + 'Pragma: no-cache' + #13#10;
    Header := Header + 'Cache-Control: no-cache' + #13#10;
    Header := Header + 'User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705)' + #13#10;
    Header := Header + 'Host: ' + SerAddr + ':' + IntToStr(ServerPort) + #13#10;
    If IsProxy Then Header := Header + 'Proxy-Connection: Keep-Alive' + #13#10 Else Header := Header + 'Connection: Keep-Alive' + #13#10;
    Header := Header + #13#10;
    CS.Socket.SendText(Header);

    //服务器返回 待下载文件的文件大小.
    Total := 0;
    While CS.Active = true Do
    Begin
      If IsStop = true Then Break;
      Cmd := SocketRec(CS.Socket, 60 * 1000);
      If Pos(LowerCase('Content-Length: '), LowerCase(Cmd)) = 1 Then Total := StrToInt(Trim(Copy(Cmd, Length('Content-Length: ') + 1, Length(Cmd))));
      If Cmd = #13#10 Then Break;
      application.ProcessMessages;
    End;
    //获取下载文件数据
    CS.Active := false;
    CS.Active := true;
    Header := '';
    If IsProxy Then
    Begin
      Header := Header + 'GET Http://' + SerAddr + ':' + IntToStr(ServerPort) + '/' + ServerFile + ' HTTP/1.0' + #13#10;
      If ProxyUser <> '' Then Header := Header + 'Proxy-Authorization: Basic ' + Base64EnCodeStr(ProxyUser + ':' + ProxyPass) + #13#10;
    End
    Else Header := Header + 'GET /' + ServerFile + ' HTTP/1.1' + #13#10;
    Header := Header + 'Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*' + #13#10;
    Header := Header + 'User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705)' + #13#10;
    Header := Header + 'RANGE: bytes=' + IntToStr(DownPos) + '-' + #13#10;
    Header := Header + 'Host: ' + SerAddr + ':' + IntToStr(ServerPort) + #13#10;
    If IsProxy Then Header := Header + 'Proxy-Connection: Keep-Alive' + #13#10 Else Header := Header + 'Connection: Keep-Alive' + #13#10;
    Header := Header + #13#10;
    CS.Socket.SendText(Header);
    //返回待下载文件大小.
    Reclen := 0;
    While CS.Active = true Do
    Begin
      If IsStop = true Then Break;
      Cmd := SocketRec(CS.Socket, 60 * 1000);
      If Pos(LowerCase('Content-Range:'), LowerCase(Cmd)) = 1 Then IsRec := true;
      If Pos(LowerCase('Content-Length: '), LowerCase(Cmd)) = 1 Then Reclen := StrToInt(Trim(Copy(Cmd, Length('Content-Length: ') + 1, Length(Cmd))));
      If Cmd = #13#10 Then Break;
      application.ProcessMessages;
    End;
    //跟着 开始接收服务器发过来的文件数据..
    Real_Reclen := 0;
    While CS.Active = true Do
    Begin//判断是否下载完成
      If IsStop = true Then Break;
      If IsRec = false Then Break;
      If FileSize(FF) >= Total Then
      Begin
      result := true;
      Break;
      End;
      //接收文件数据
      ZeroMemory(@Buf, SizeOf(Buf));
      Rec := CS.Socket.ReceiveBuf(Buf, SizeOf(Buf));
//判断是否下载完成
      If Real_Reclen >= Reclen Then
      Begin
      //文件已经下载完毕
      result := true;
      Break;
      End;
//判断是否下载完成
      If DownPos = Reclen Then
      Begin
      //文件已经下载完毕
      result := true;
      Break;
      End;
//写入到文件
      BlockWrite(FF, Buf, Rec);
      Real_Reclen := Real_Reclen + Rec;

      //显示下载进度
      Progress(Real_Reclen, Reclen);

      application.ProcessMessages;
    End;
    CloseFile(FF);
    CS.Active := false;
Except
    CloseFile(FF);
    result := false;
End;
End;

canspider 发表于 2015-3-24 20:59:45

所谓http就是字符串拼接而已

billtian 发表于 2015-3-24 21:03:35

谢谢大家,我好好研究一下

billtian 发表于 2015-3-24 21:58:32

看到了,1460+1460+1460+966=5326 但是这几个包是在哪里发的呢,抓包工具看不到吗?

hyz_avr 发表于 2015-3-24 22:11:00

billtian 发表于 2015-3-24 21:58
看到了,1460+1460+1460+966=5326 但是这几个包是在哪里发的呢,抓包工具看不到吗? ...

就是TCP Socket

billtian 发表于 2015-3-24 22:36:52

hyz_avr 发表于 2015-3-24 22:11
就是TCP Socket

抓包那个时间我怎么总看着是反的?发送数据包时间靠前啊,但是显然又不合理,怪了

sun92845166 发表于 2015-3-26 00:14:28

需要能力较强的嵌入式开发人员和PC平台程序员,图像处理方向

billtian 发表于 2015-3-27 15:05:35

前2天有位朋友给贴了一段代码,我当时没仔细看,能在帮忙发一下吗?谢谢了!

shell.albert 发表于 2015-3-27 17:30:30

看到使用WireShark抓包了。

wazhiyi 发表于 2016-5-26 10:03:16

yeelink不错

lovewind 发表于 2016-6-4 08:31:42

wazhiyi 发表于 2016-5-26 10:03
yeelink不错

yeelink 太难了,都是json,执行操作还慢,我发现了个比较好玩的,fuhome,就是简单的协议,响应速度比yelink快,{:lol:} ,不过最近准备用w5500搞的,enc28j60太麻烦了,协议栈一大堆{:funk:}
页: [1]
查看完整版本: C#中的HttpWebRequest底层是如何实现的? yeelink上传图片