DOBON.NET DOBON.NETプログラミング掲示板過去ログ

Socket通信でパケットを意図的に分割する

環境/言語:[OS : Windows XP Professional / 言語 : Visual Basic .NET]
分類:[.NET]

【解決したい問題】

 お世話になっております。
 Socket通信で、パケットを意図的に分割する方法についてご教示願います。
 現在、変数:SocketReturn(0)〜SocketReturn(2)に送信したいデータが
格納されており、以下のプログラムを実施すると、
  ・ SocketReturn(0)が1パケットで送信
  ・ SocketReturn(1)とSocketReturn(2)が1パケットで送信
されてしまいます。

 プログラムでは、SocketReturn(0)〜(2)を分けて送信しているつもりなのですが、
SocketReturn(1)とSocketReturn(2)が1パケットに纏められて送信されてしまいます。

 お手数ですが、ご教示方よろしくお願い致します。
 
 環境:
  WindowsXP(SP2)
  Microsoft Visual Studio .NET 2003


☆☆☆☆☆ 以下、プログラム ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆

Public Sub SendData()

Dim i As Long

'文字コードを指定する
Dim enc As System.Text.Encoding = System.Text.Encoding.UTF8

'サーバーのホスト名とポート番号
Dim host As String = RemoteIp
Dim port As Integer = RemotePort

'TcpClientを作成し、サーバーと接続する
Dim tcp As New System.Net.Sockets.TcpClient(host, port)

'NetworkStreamを取得する
Dim ns As System.Net.Sockets.NetworkStream = tcp.GetStream()

'サーバーにデータを送信する
'送信するデータを入力
Dim sendMsg As String
SocketReturn(0) = "111111111111111111111111111111111111111111111111111111111111"
SocketReturn(1) = "222222222222222222222222222222222222222222222222222222222222"
SocketReturn(2) = "333333333333333333333333333333333333333333333333333333333333"

For i = 0 To 2
sendMsg = SocketReturn(i)
'sendMsg = SocketReturn(i)
'何も入力されなかった時は切断する
If sendMsg = "" Then
tcp.Close()
Return
End If

'文字列をByte型配列に変換
Dim sendBytes As Byte() = enc.GetBytes(sendMsg)

'データを送信する
ns.Write(sendBytes, 0, sendBytes.Length)
Next i

'閉じる
ns.Close()
tcp.Close()

End Sub

 
☆☆☆☆☆ 以下、パケットのキャプチャ内容 ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆

---------------------------------------------------------------------------------
00 01 02 03 04 05 06 07-08 09 0A 0B 0C 0D 0E 0F 0123456789ABCDEF
+-------------------------------------------------+-----------------+
00000000 |
00000010 |
00000020 | 50 18 FF FF 16 EC 00 00-31 31 31 31 31 31 31 31 | P..・.11111111
00000030 | 31 31 31 31 31 31 31 31-31 31 31 31 31 31 31 31 | 1111111111111111
00000040 | 31 31 31 31 31 31 31 31-31 31 31 31 31 31 31 31 | 1111111111111111
00000050 | 31 31 31 31 31 31 31 31-31 31 31 31 31 31 31 31 | 1111111111111111
00000060 | 31 31 31 31 | 1111
---------------------------------------------------------------------------------
00 01 02 03 04 05 06 07-08 09 0A 0B 0C 0D 0E 0F 0123456789ABCDEF
+-------------------------------------------------+-----------------+
00000000 |
00000010 |
00000020 | 50 19 FF FF F8 54 00 00-32 32 32 32 32 32 32 32 | P.T..22222222
00000030 | 32 32 32 32 32 32 32 32-32 32 32 32 32 32 32 32 | 2222222222222222
00000040 | 32 32 32 32 32 32 32 32-32 32 32 32 32 32 32 32 | 2222222222222222
00000050 | 32 32 32 32 32 32 32 32-32 32 32 32 32 32 32 32 | 2222222222222222
00000060 | 32 32 32 32 33 33 33 33-33 33 33 33 33 33 33 33 | 2222333333333333
00000070 | 33 33 33 33 33 33 33 33-33 33 33 33 33 33 33 33 | 3333333333333333
00000080 | 33 33 33 33 33 33 33 33-33 33 33 33 33 33 33 33 | 3333333333333333
00000090 | 33 33 33 33 33 33 33 33-33 33 33 33 33 33 33 33 | 3333333333333333
---------------------------------------------------------------------------------

☆☆☆☆☆ 以下、実施したいパケットの送信内容 ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆

---------------------------------------------------------------------------------
00 01 02 03 04 05 06 07-08 09 0A 0B 0C 0D 0E 0F 0123456789ABCDEF
+-------------------------------------------------+-----------------+
00000000 |
00000010 |
00000020 | 50 18 FF FF 16 EC 00 00-31 31 31 31 31 31 31 31 | P..・.11111111
00000030 | 31 31 31 31 31 31 31 31-31 31 31 31 31 31 31 31 | 1111111111111111
00000040 | 31 31 31 31 31 31 31 31-31 31 31 31 31 31 31 31 | 1111111111111111
00000050 | 31 31 31 31 31 31 31 31-31 31 31 31 31 31 31 31 | 1111111111111111
00000060 | 31 31 31 31 | 1111
---------------------------------------------------------------------------------
00 01 02 03 04 05 06 07-08 09 0A 0B 0C 0D 0E 0F 0123456789ABCDEF
+-------------------------------------------------+-----------------+
00000000 |
00000010 |
00000020 | 50 18 FF FF 16 EC 00 00-32 32 32 32 32 32 32 32 | P..・.22222222
00000030 | 32 32 32 32 32 32 32 32-32 32 32 32 32 32 32 32 | 2222222222222222
00000040 | 32 32 32 32 32 32 32 32-32 32 32 32 32 32 32 32 | 2222222222222222
00000050 | 32 32 32 32 32 32 32 32-32 32 32 32 32 32 32 32 | 2222222222222222
00000060 | 32 32 32 32 | 2222
---------------------------------------------------------------------------------
00 01 02 03 04 05 06 07-08 09 0A 0B 0C 0D 0E 0F 0123456789ABCDEF
+-------------------------------------------------+-----------------+
00000000 |
00000010 |
00000020 | 50 18 FF FF 16 EC 00 00-33 33 33 33 33 33 33 33 | P..・.33333333
00000030 | 33 33 33 33 33 33 33 33-33 33 33 33 33 33 33 33 | 3333333333333333
00000040 | 33 33 33 33 33 33 33 33-33 33 33 33 33 33 33 33 | 3333333333333333
00000050 | 33 33 33 33 33 33 33 33-33 33 33 33 33 33 33 33 | 3333333333333333
00000060 | 33 33 33 33 | 3333
---------------------------------------------------------------------------------

のように送りたい。
■No19650に返信(acyacyaさんの記事)
> 【解決したい問題】
>
>  お世話になっております。
>  Socket通信で、パケットを意図的に分割する方法についてご教示願います。
>  現在、変数:SocketReturn(0)〜SocketReturn(2)に送信したいデータが
> 格納されており、以下のプログラムを実施すると、
>   ・ SocketReturn(0)が1パケットで送信
>   ・ SocketReturn(1)とSocketReturn(2)が1パケットで送信
> されてしまいます。
>
>  プログラムでは、SocketReturn(0)〜(2)を分けて送信しているつもりなのですが、
> SocketReturn(1)とSocketReturn(2)が1パケットに纏められて送信されてしまいます。

TCP の仕様です。
ソケットを使う以上、宿命と思ってあきらめましょう。

送る側で何回かに分けて送っても、受ける側ではまとめて受けるかもしれませんし、分けて受けるかもしれません。
送る側で1回だけ送っても、受ける側では複数回に分けて受け取るかもしれませんし、1回で受けるかもしれません。
ソケットプログラムは、そういうことが起こることを想定して作らなければなりません。
具体的には、受け取る側が、どこが前のデータと次のデータの境目なのかを判別できるように、データ形式を決めなければならないということになります。
シャノンさま

 ご回答頂きありがとうございました。

> TCP の仕様です。
> ソケットを使う以上、宿命と思ってあきらめましょう。

 パケット分割は、TCPの気まぐれで変化すると思っていたのですが、何十回
送受信を繰り返しても、必ずパケットの分かれ方が同じだったので、1セッション
の中で何度もデータ送信を行うロジックに間違いがあると思い込んで、四苦八苦
しておりました。

> 具体的には、受け取る側が、どこが前のデータと次のデータの境目なのかを判別できるように、データ形式を決めなければならないということになります。

 データの構造から再度検討してみます。

 ありがとうございました。
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板