TCP服务端【接收端】- 原数据图传.ahk

; ================== 以下函数仅做记录存档之用 ==================

; Server 【TCP连接需要注意先后顺序,顺序不对会处于阻塞等待状态】
SetBatchLines -1
#SingleInstance Force
SetWorkingDir %A_ScriptDir%
#Include %A_ScriptDir%/Socket.ahk

pToken := Gdip_StartUp()  ; GDI库加载

myTcp := New SocketTCP()
myTcp.onAccept := Func("OnTCPAccept")
myTcp.bind("0.0.0.0", 22345)
myTcp.listen()
Return

; 收到信息时触发
OnTCPAccept() {
    Global
    newTcp := myTcp.accept()
    ; newTcp.sendText("接收端 → 向 → 发送端的回复")
    ; MsgBox % newTcp.RecvText()  ; 接收发送端的信息
    ; bytes :=newTcp.Recv(buf)  ; 用于接收发送端的二进制,不能大于65536字节=64KB
    ; pToken := Gdip_StartUp()  ; GDI库加载
    ; hBitmap := GDIPlus_hBitmapFromBuffer(buf, bytes)
    ; Gui, Add, Picture, , % "HBITMAP:*" hBitmap
    ; Gui, Show, AutoSize
    ; Sleep 2000
    ; ExitApp

/*
    pBitmap := Gdip_BitmapFromBase64(newTcp.RecvText())  ; Base64转pBitmap
    hBitmap := Gdip_CreateHBITMAPFromBitmap(pBitmap)
    Gui, Add, Picture, vPic, % "HBITMAP:*" hBitmap
    Gui, Show, w1000 h700, AHK窗口显示
*/

    MsgBox % readbytes :=newTcp.Recv(data)  ; 用于接收发送端的二进制,不能大于65536字节=64KB
    w := NumGet(data, 0, "int")
    h :=  NumGet(data, 4, "int")
    planes :=  NumGet(data, 8, "ushort")
    bitsPixel :=  NumGet(data, 10, "ushort")
    bits := &data + 12
    ; MsgBox % w """" h """" planes """" bitsPixel """" bits
    hBitmap := DllCall("CreateBitmap", "int", w, "int", h, "Uint", planes, "Uint", bitsPixel, "Ptr", bits, "Ptr")
    gui, add, picture,, % "HBITMAP:*" hBitmap
    gui, show, w500 h500
    ; hBitmap := DllCall("CreateBitmap", "int", bitmap.w, "int", bitmap.h, "Uint", bitmap.planes, "Uint", bitmap.bitsPixel, "Ptr", bitmap.bits, "Ptr")
    
    ; file2 := FileOpen("PsExec5.png","w")
    ; writebytes := file2.RawWrite(&buf, readbytes)
    ; file2.close()
    ; MsgBox % Clipboard := newTcp.RecvHex()  ; 用于接收发送端的16进制信息
    Sleep 2000
    

    ExitApp
}


;GdiPlus_SaveImageToBuffer() - Scripts and Functions - AutoHotkey Community
;https://autohotkey.com/board/topic/85523-gdiplus-saveimagetobuffer/

GDIPlus_hBitmapFromBuffer(ByRef Buffer, nSize) {  ; by SKAN
  hData := DllCall("GlobalAlloc", "Uint", 2, "Uint", nSize)
  pData := DllCall("GlobalLock", "Uint", hData)
  DllCall("RtlMoveMemory", "Uint", pData, "Uint", &Buffer, "Uint", nSize)
  DllCall("GlobalUnlock", "Uint", hData)
  DllCall("ole32\CreateStreamOnHGlobal", "Uint", hData, "int", True, "UIntP", pStream)
  DllCall("gdiplus\GdipCreateBitmapFromStream",  "Uint", pStream, "UIntP", pBitmap)
  DllCall("gdiplus\GdipCreateHBITMAPFromBitmap", "Uint", pBitmap, "UIntP", hBitmap, "Uint", DllCall("ntdll\RtlUlongByteSwap", "Uint", DllCall("GetSysColor", "int", 15 ) <<8 ) | 0xFF000000)
  DllCall("gdiplus\GdipDisposeImage", "Uint", pBitmap)
  DllCall(NumGet( NumGet(1*pStream)+8 ), "Uint", pStream)  ; IStream::Release
  Return hBitmap
}



/*
; 收到信息时触发【传输文件示例】
OnTCPAccept() {
    Global
    newTcp := myTcp.accept()
    收到信息 := newTcp.recvText()
    if (收到信息="传输文件")
        newTcp.RecvFilePackages("D:\")  ; 接收文件速率较慢
    ExitApp
}
*/

 

TCP客户端【发送端】- 原数据图传.ahk

; ================== 以下函数仅做记录存档之用 ==================

; Client 【TCP连接需要注意先后顺序,顺序不对会处于阻塞等待状态】
SetBatchLines -1
#SingleInstance Force
SetWorkingDir %A_ScriptDir%
#Include %A_ScriptDir%/Socket.ahk

pToken := Gdip_StartUp()  ; GDI库加载

Global myTcp := New SocketTCP()
myTcp.Connect("127.0.0.1", 22345)  ; 支持动态域名解析,比如:myname.f3322.net

/*        Base64压缩成文件对比测试,单次发送大于64KB会图片缺失
pBitmap := Gdip_BitmapFromScreen("0|0|1000|600")
pStream := Gdip_SaveBitmapToFile(pBitmap, "none.jpg", 30)  ; 截图保存文件
Clipboard := Gdip_BitmapToBase64(pBitmap, "JPG", 30)  ; Base64到剪贴板
myTcp.SendText(Gdip_BitmapToBase64(pBitmap, "JPG", 30))
Gdip_DisposeImage(pBitmap)
ExitApp
*/

; myTcp.SendText("向接收端 →→ 发送文字")  ; 发送信息为空会导致,服务端失去响应
; FileRead, memWav, *c D:\PSTools\图标\11原图.png

; file := FileOpen("D:\PSTools\图标\11原图.png", "r")
; readbytes := file.RawRead(buff, size)
; file.close()

; vSize := File.Length ; 应该是获取文件大小
; readbytes和size都是文件大小的返回

; pToken := Gdip_StartUp()  ; GDI库加载

; pBitmap := Gdip_CreateBitmapFromFile("D:\PSTools\图标\11原图.png")  ; 读取指定图片到pBitmap
; hBitmap := Gdip_CreateHBITMAPFromBitmap(pBitmap)  ; pBitmap转hBitmap


; MsgBox % size := GdiPlus_SaveImageToBuffer( pBitmap, Bitmap, "PNG")

; Bitmap := GetBitmap(hBitmap)
; Bitmap2 := CryptBinaryToString(Bitmap.bits, Bitmap.widthBytes * Bitmap.h + Bitmap.planes * Bitmap.bitsPixel, 0x0000000a)

; size := Bitmap.widthBytes * Bitmap.h + Bitmap.planes * Bitmap.bitsPixel
; FileGetSize, Size, D:\PSTools\图标\QQ截图20220829005440.bmp

; FileGetSize, Size, D:\PSTools\图标\11原图.png
; FileRead, Bitmap, *c D:\PSTools\图标\11原图.png
; myTcp.send(&Bitmap, size)


; hBitmap := LoadPicture("D:\PSTools\图标\QQ截图20220829005440.bmp")  ; 图像会翻转
hBitmap := LoadPicture("D:\PSTools\图标\11原图.png")  ; 图像会翻转


; pBitmap := Gdip_BitmapFromScreen("0|0|1000|600")
; 
; MsgBox % bytes := GdiPlus_SaveImageToBuffer(pBitmap, Buf, "JPG", 30)
; file := FileOpen("test.jpg","w")
; writebytes := file.RawWrite(&Buf, bytes)
; file.close()
; myTcp.send(&Buf, bytes)

; /*
; pStream := Gdip_SaveBitmapToFile(pBitmap, "none.jpg", 30, 2)
; Clipboard := Gdip_BitmapToBase64(pBitmap, "JPG", 30)
; pBitmap := Gdip_CreateBitmapFromStream(pStream)
; hBitmap := Gdip_CreateHBITMAPFromBitmap(pBitmap)  ; pBitmap转hBitmap

Bitmap := GetBitmap(hBitmap)
; MsgBox % Bitmap.type "`n" Bitmap.w "`n" Bitmap.h "`n" Bitmap.widthBytes "`n" Bitmap.planes "`n" Bitmap.bitsPixel "`n" Bitmap.bits

; FileGetSize, Size, D:\PSTools\图标\QQ截图20220829005440.bmp  ; 4962
; 把信息和数据区结合在一块内存可一次性发送, 分两次发送能省复制内存的时间, 不知两者效率如何
; size := bitmap.widthBytes * bitmap.h + bitmap.planes * bitmap.bitsPixel  ; 4940   1976
size := bitmap.widthBytes * bitmap.h  ; by zzZ  1944
VarSetCapacity(data, size+12)
NumPut(bitmap.w, data, 0, "int")
NumPut(bitmap.h, data, 4, "int")
NumPut(bitmap.planes, data, 8, "UShort")
NumPut(bitmap.bitsPixel, data, 10, "UShort")
DllCall("RtlCopyMemory", "Ptr", &data+12, "Ptr", bitmap.bits, "UPtr", size)
myTcp.Send(&data, size+12)
; */

; myTcp.SendHex(0x01, 0x05, 0x00, 0xFF, 0x8c, 0x3a, 0x45)  ; 发送16进制信息示例
Sleep 1000
ExitApp

/*     临时记录
hBitmap := LoadPicture(A_AhkPath)
Bitmap := GetBitmap(hBitmap)

OutputDebug % CryptBinaryToString(Bitmap.bits, Bitmap.widthBytes * Bitmap.h + Bitmap.planes * Bitmap.bitsPixel, 0x0000000a)

CryptBinaryToString(addr, bytes, flag := 0x40000004){
    DllCall("crypt32\CryptBinaryToStringW", "ptr", addr, "uint", bytes, "uint", flag, "ptr", 0, "uint*", chars)
    VarSetCapacity(hex, chars * 2)
  DllCall("crypt32\CryptBinaryToStringW", "ptr", addr, "uint", bytes, "uint", flag, "str", hex, "uint*", chars)
  return hex
}
*/



; 资料:https://www.autohotkey.com/boards/viewtopic.php?f=76&t=39002
; 出处:https://www.autohotkey.com/boards/viewtopic.php?f=6&t=33209
GetBitmap(hBitmap){
  ;  https://msdn.microsoft.com/en-us/library/windows/desktop/dd144904%28v=vs.85%29.aspx 	(GetObject function)
  ;  https://msdn.microsoft.com/en-us/library/windows/desktop/dd183371(v=vs.85).aspx  (BITMAP structure)
  static pBits := A_PtrSize==4 ? 20 : 24
  local BITMAP, cbBuffer, nBytes

  ; Get the requiered size of the buffer (BITMAP)
  if !(cbBuffer:=DllCall("Gdi32.dll\GetObject", "Ptr", hBitmap, "int", cbBuffer, "Ptr", 0))
    throw Exception("Failed to get the requiered buffer size, ErrorLevel: " ErrorLevel " Last error: " A_LastError ".", -1)
  VarSetCapacity(BITMAP, cbBuffer, 0)
  if !(nBytes:=DllCall("Gdi32.dll\GetObject", "Ptr", hBitmap, "int", cbBuffer, "Ptr", &BITMAP) == cbBuffer) ; Get the BITMAP
    throw Exception("Failed to get the bitmap object, ErrorLevel: " ErrorLevel " Last error: " A_LastError ".",-1)

  BITMAP := {type: NumGet(&BITMAP, 0, "int")  ; bmType
        , w: NumGet(&BITMAP, 4, "int")  ; bmWidth
        , h: NumGet(&BITMAP, 8, "int")  ; bmHeight
        , widthBytes: NumGet(&BITMAP, 12, "int")  ; bmWidthBytes
        , planes: NumGet(&BITMAP, 16, "UShort")  ; bmPlanes
        , bitsPixel: NumGet(&BITMAP, 18, "UShort")  ; bmBitsPixel
        , bits: NumGet(&BITMAP, pBits, "Ptr")}  ; bmBits

  return BITMAP
}


GdiPlus_SaveImageToBuffer(pBitmap, ByRef Buffer, Type:="JPG", Quality:=75) {
  Static Ptr := "UPtr"
  nCount := nSize := pStream := hData := _p := 0

  If !RegExMatch(Type, "^(?i:BMP|DIB|RLE|JPG|JPEG|JPE|JFIF|GIF|TIF|TIFF|PNG)$")
    Return -1

  Type := "." Type
  , DllCall("gdiplus\GdipGetImageEncodersSize", "uint*", nCount, "uint*", nSize)
  , VarSetCapacity(ci, nSize)
  , DllCall("gdiplus\GdipGetImageEncoders", "uint", nCount, "uint", nSize, Ptr, &ci)
  If !(nCount && nSize)
    Return -2

  If A_IsUnicode {
    StrGet_Name := "StrGet"
    , N := (A_AhkVersion < 2) ? nCount : "nCount"
    Loop %N% {
      sString := %StrGet_Name%(NumGet(ci, (idx := (48+7*A_PtrSize)*(A_Index-1))+32+3*A_PtrSize), "UTF-16")
      If !InStr(sString, "*" Type)
        Continue

      pCodec := &ci+idx
      Break
    }
  } Else {
    N := (A_AhkVersion < 2) ? nCount : "nCount"
    Loop %N% {
      Location := NumGet(ci, 76*(A_Index-1)+44)
      , nSize := DllCall("WideCharToMultiByte", "uint", 0, "uint", 0, "uint", Location, "int", -1, "uint", 0, "int", 0, "uint", 0, "uint", 0)
      , VarSetCapacity(sString, nSize)
      , DllCall("WideCharToMultiByte", "uint", 0, "uint", 0, "uint", Location, "int", -1, "str", sString, "int", nSize, "uint", 0, "uint", 0)
      If !InStr(sString, "*" Type)
        Continue

      pCodec := &ci+76*(A_Index-1)
      Break
    }
  }

  If !pCodec
    Return -3

  If (Quality!=75) {
    Quality := (Quality < 0) ? 0 : (Quality > 100) ? 100 : Quality
    If (quality>95 && toBase64=1)
      Quality := 95

    If RegExMatch(Type, "^\.(?i:JPG|JPEG|JPE|JFIF)$") {
      DllCall("gdiplus\GdipGetEncoderParameterListSize", Ptr, pBitmap, Ptr, pCodec, "uint*", nSize)
      , VarSetCapacity(EncoderParameters, nSize, 0)
      , DllCall("gdiplus\GdipGetEncoderParameterList", Ptr, pBitmap, Ptr, pCodec, "uint", nSize, Ptr, &EncoderParameters)
      , nCount := NumGet(EncoderParameters, "UInt")
      , N := (A_AhkVersion < 2) ? nCount : "nCount"
      Loop %N% {
        elem := (24+A_PtrSize)*(A_Index-1) + 4 + (pad := A_PtrSize = 8 ? 4 : 0)
        If (NumGet(EncoderParameters, elem+16, "UInt") = 1) && (NumGet(EncoderParameters, elem+20, "UInt") = 6) {
          _p := elem+&EncoderParameters-pad-4
          NumPut(Quality, NumGet(NumPut(4, NumPut(1, _p+0)+20, "UInt")), "UInt")
          Break
        }
      }
    }
  }

  ; Save Image to Stream and copy it to Buffer
  DllCall( "ole32\CreateStreamOnHGlobal", "Uint", 0, "int", 1, "UintP", pStream )
  , DllCall( "gdiplus\GdipSaveImageToStream", "Uint", pBitmap, "Uint", pStream, "Uint", pCodec, "Uint", _p )
  , DllCall( "gdiplus\GdipDisposeImage", "Uint", pBitmap )
  , DllCall( "ole32\GetHGlobalFromStream", "Uint", pStream, "UintP", hData )
  , pData := DllCall( "GlobalLock", "Uint", hData )
  , nSize := DllCall( "GlobalSize", "Uint", pData )
  , VarSetCapacity( Buffer, nSize, 0 )
  , DllCall( "RtlMoveMemory", "Uint", &Buffer, "Uint", pData, "Uint", nSize )
  , DllCall( "GlobalUnlock", "Uint", hData )
  , DllCall( NumGet( NumGet( 1*pStream ) + 8 ), "Uint", pStream )
  , DllCall( "GlobalFree", "Uint", hData )
  Return nSize
}

 

声明:站内资源为整理优化好的代码上传分享与学习研究,如果是开源代码基本都会标明出处,方便大家扩展学习路径。请不要恶意搬运,破坏站长辛苦整理维护的劳动成果。本站为爱好者分享站点,所有内容不作为商业行为。如若本站上传内容侵犯了原著者的合法权益,请联系我们进行删除下架。