fenhanxue 发表于 2017-8-17 03:25:45

字符串如何分割成两段指定字符数的二进制数据,又如何转回这段字符串?【已解决】

本帖最后由 fenhanxue 于 2017-8-22 02:31 编辑

问题背景:
TCPRecv ( 主套接字,   最大返回量[, 标志])
有最大返回量的限制,假设这个最大返回量为 $max
假设发送端电脑要发送一段中英文混杂文本$text 到接收端电脑,那么分两种情况


1)文本 $text 的长度 <= $max
        这种情况我知道可以这样写代码:
        1.1)发送端
        TCPSend(主套接字,StringToBinary($text,2))
        1.2)接收端
        $receive = TCPRecv (主套接字,$max,1)
        $receive = BinaryToString($receive,2)
        这样接收端就可以最终收到完整的$text
       
       
       
2)文本 $text 的长度 > $max
        这种情况下不知道具体应该如何对$text 进行二进制分割
        假设此时:
        2* $max        >$text 的长度 > $max
       
        那么也就意味着发送端需要发送两次二进制数据
                第一次:TCPSend(主套接字,$data_1)        ($data_1 的长度 = $max)
                第二次:TCPSend(主套接字,$data_2)        ($data_2 的长度 = $text 的长度 -$max)
                这里的        $data_1 和 $data_2 具体应该怎么运算得到?
        然后此时接收端也要收两次二进制数据才行
                第一次:$receive_1 = TCPRecv (主套接字,$max,1)
                第二次:$receive_2 = TCPRecv (主套接字,$max,1)
                这里的$receive_1 和 :$receive_2 又应该如何转变回 $text ?

tubaba 发表于 2017-8-17 11:14:43

换个思路,定义二个控制字符,约定chr(1)为发送字符串开始,chr(2)为发送结束.客户端接收到chr(1),认为是字符串的开始,收到chr(2),认为发送结束,转换chr(1)与chr(2)之间的二进制数据即可

fenhanxue 发表于 2017-8-17 13:59:23

回复 2# tubaba ;假设最大返回量为9个字节
$max = 9
;假设一段文本 $text 的长度在 9 到18之间
$text
;那么这段代码是否有问题:
Local $binary = StringToBinary($text,2)
;二进制分成两部分:
$binary_1 = BinaryMid($binary,1,$max)
$binary_2 = BinaryMid($binary,1+$max)
;发送端发送两次,分别为:
                TCPSend(主套接字,$binary_1);第一次
                TCPSend(主套接字,$binary_2);第二次
;接收端接受两次,分别为:
      $receive_1 = TCPRecv (主套接字,$max,1) ;第一次
                $receive_2 = TCPRecv (主套接字,$max,1) ;第二次
                ;接收端完整收到的信息为:
                BinaryToString($receive_1&$receive_2,2)

tubaba 发表于 2017-8-17 15:11:19

本帖最后由 tubaba 于 2017-8-17 15:12 编辑

存在一个数据类型转换问题,定义收到04即接收完成
Func _TCPRecv()
        Local $recv, $string = ''
        While 1
                $recv = TCPRecv($ConnectedSocket, 9, 1)
                If ($recv = '' And (Not @error)) Or @error Then ExitLoop
                If $recv <> '' Then
                        $string &= StringRegExpReplace($recv, '(?:0x)(.+)', '$1')
                        If StringRight($string, 2) == '04' Then ExitLoop
                EndIf
        WEnd
;~         $string= BinaryToString('0x' & $string, 4)
        If StringRight($string, 2) == '04' Then
                $string = BinaryToString('0x' & StringTrimRight($string, 2), 4)
        Else
                $string = BinaryToString('0x' & $string, 4)
        EndIf
        If $string = '' Then Return SetError(1, 0, $string)
;~         FileWrite('out1.txt',$string)
        Return SetError(0, 0, $string)
EndFunc   ;==>_TCPRecv

fenhanxue 发表于 2017-8-17 17:13:39

回复 4# tubaba

假设自定义收到的 $end = '04'作为接收完成的标记,

有没有可能会遇到特殊情况:
某一段字符串 经过 stringtobinary 后,凑巧他的末尾两位 等于$end ( '04' )?

那么这样的话,就会误判以为接收完成了。
有没什么字符串,是 stringtobinary 后绝对不会出现的?

kk_lee69 发表于 2017-8-17 17:35:59

回复 5# fenhanxue


    我記得範例有人有傳輸檔案的範例 中間好幾MB 都可以傳
所以理論上應該有處理這個的範例

yamakawa 发表于 2017-8-17 18:05:30

回复 6# kk_lee69


    抱歉,插楼。。。。。我看见你去官网问 大神 LarsJ。修改选定项颜色用很短的代码搞定了。。。请问,你能同时指定某列的颜色么?

kk_lee69 发表于 2017-8-17 18:11:15

回复 7# yamakawa


    看來就是不行你可以去看我 另外再發問的 .......

就是我怎麼測試都不行

只是我不能理解的是   官網的 是不用另外做GDI 然後再合併進去

我們之前的方式 似乎是另外的人的是 畫了一個GDI 然後再合併進去

但是使用 官網的 那個方法 我的 複選框 功能失效

yamakawa 发表于 2017-8-17 18:18:15

回复 8# kk_lee69


    理论上,官网那个才是正宗的,因为用的是本来的数据结构,只是更改了某些参数,这个兼容性更好。但是我没找到资料$CDDS_ITEMPREPAINT之类的参数到底有什么关系,为什么有时候有些参数可以,有些不行,,,
gdi那个是直接干掉原来现实的部分直接画上去。所以原来有的某些特性,比如复选框,就没有了。需要我们自己画

fenhanxue 发表于 2017-8-17 18:18:19

本帖最后由 fenhanxue 于 2017-8-17 18:20 编辑

回复 6# kk_lee69


    可能是这个帖子:
http://autoitx.com/forum.php?mod=viewthread&tid=17177&highlight=tcp%2B%CE%C4%BC%FE

范例是档案传输 ,几个关键代码为
发送端:   FileOpen($hfile,16)
   While
           $data = FileRead($id,$max);不断循环读取指定长度的二进制数据
           If @error=-1 Then ExitLoop
           TCPSend($netid,$data)
   WEnd接收端:        $file = FileOpen ($hfile,16+1)
        While
                $receive = TCPRecv($ConnectedSocket,$max)
                If @error=-1 Then ExitLoop
                FileWrite($file,Binary($data))
        WEnd我想传输的是程序里的一段长文本(假设为$text),而不是文件,所以需要对 $text 进行分割,而如何将这个 $text 变成二进制数据,并且按照指定的字符长度进行分割,原理不是很懂。

当然如果笨一点的办法,可以参考上面的范例这样写:
接收端:
先把 $text 写到一个txt档案里,然后套用上面的范例代码,读取这个档案,来发送。
接收的时候,也套用上面的代码,接收到一个txt档案里,然后再FileOpen ($hfile,0) 来读取这个txt档案

yamakawa 发表于 2017-8-17 18:58:59

回复 8# kk_lee69


我这边的测试效果好搞笑

{:face (394):} 好像没有更新?!要点一下其他行才会变化

yamakawa 发表于 2017-8-17 19:34:24

本帖最后由 yamakawa 于 2017-8-17 19:35 编辑

回复 8# kk_lee69


    好像可以了。。。。。

修改$NM_CLICK消息为                                Case $NM_CLICK ; Sent by a list-view control when the user clicks an item with the left mouse button
                                        Local $tInfo = DllStructCreate($tagNMITEMACTIVATE, $ilParam)
                                        Local $Index = DllStructGetData($tInfo, "Index"), _
                                                        $X = DllStructGetData($tInfo, "X")
                               
                                        If $X < 18 Then ;使用x坐标来判断是否在复选框上点击
                                                If $aShowdata2[$Index] = 4096 Then
                                                        $aShowdata2[$Index] = 8192 ;4096未选中 8192选中
                                                Else
                                                        $aShowdata2[$Index] = 4096 ;4096未选中 8192选中
                                                EndIf
                                        EndIf
                                        Local $Info = DllStructCreate($tagNMLVDISPINFO, $ilParam)

                                        DllStructSetData($Info, "State", $aShowdata2[$Index]) ;设置复选框状态
                                        _GUICtrlListView_RedrawItems($hWndFrom, $Index, $Index);<====好像可以了。。。。复选框正常
现在我的问题是。。不知道怎么可以单独设置某个列的颜色。。。原来那个代码好像不起作用了。。好奇怪

yamakawa 发表于 2017-8-17 19:46:22

回复 10# fenhanxue


    抱歉,楼主,在你的帖子插楼。。。
我想传输的是程序里的一段长文本(假设为$text),而不是文件,所以需要对 $text 进行分割,而如何将这个 $text 变成二进制数据,并且按照指定的字符长度进行分割,原理不是很懂

这个的话,可以先用StringToBinary转换成二进制数据,然后BinaryLen可以获取字节数,然后根据字节数进行判断,分解成小于max的数据,用BinaryMid(提取二进制变量的若干字节.)

yamakawa 发表于 2017-8-17 20:08:43

回复 13# yamakawa


    另外。。tcpsend成功的话,会返回成功发送的字节数,可以把这个当参数传递给下一次传输。例如这次传输了2048个字节,那么下次binarymid就从2049开始

yamakawa 发表于 2017-8-17 20:14:08

本帖最后由 yamakawa 于 2017-8-17 20:22 编辑

回复 5# fenhanxue


    另外。4楼说的定义04就是接受完成的意思。一般来说。传输数据不会是04结尾的,但是如果实在怕不保险的话,

你可以定义某个开始特征码和完成特征码。。
   第一次发送开始码,接收端收到后就知道下次开始是发送的多次信息,
然后全部发送完成后,发送端再发送完成码,接收端知道信息已经接收完毕了。那么就对之前接收到的数据进行合并,转换操作
页: [1] 2
查看完整版本: 字符串如何分割成两段指定字符数的二进制数据,又如何转回这段字符串?【已解决】