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

.NETでデータの送信を完了できない。

環境/言語:[XP VB.NET]
分類:[.NET]

はじめまして、ちゃと申します。
プログラム初心者(少し”?”が付きます)です。

現在、同一セグメント内のLAN内にあるクライアント側PCからサーバ側PCへデータ
を送信するプログラムを作成したのですが上手く通信が完了しません。

サーバ側のプログラムをアタッチして処理を行うと確実にデータが送信されるので
すが、アタッチしないとデータが送信できない状況です。

キャプチャソフトを使って、データの流れを追っているとサーバ側からFIN信号を
投げているがクライアント側がAckを返してないため、セッションを切断されてい
る事が分かりました。しかし、アタッチしている際のFIN信号に対するAckの待ち時
間は、0.12秒〜0.22秒位なのですが、アタッチしていない時の待ち時間が0.06秒位
しか待っていないんです。

サーバ側の処理にクライアント側の処理が追いついていないと思い、サーバ側の処
理を遅らせるためThread.sleepで200ミリ秒待つように指定したのですが上手くデ
ータが送信されません。

VBでTCPの実装レベル(あってますか?)を制御してFIN要求を遅らせる方
法がありますか?

もしくは、何かしらの回避方法はあるのでしょうか?

正常な流れとしては、
サーバ   →クライアント :データ送信要求
クライアント→サーバ    :接続要求〜データ送信
サーバ   →クライアント :送信完了通知(データの先頭部に記述し送信)
クライアント→サーバ    :切断

現状
サーバ   →クライアント :データ送信要求
クライアント→サーバ    :接続要求〜データ送信
サーバ   →クライアント :送信完了通知(データの先頭部に記述し送信)
サーバ   →クライアント :切断要求
サーバ   →クライアント :Ack待ち時間経過
サーバ   →クライアント :RSETにより切断

といった感じになっています。

ヘビーな内容にも関わらず、貧相な内容ですいません。もともとプログラミング
というよりネットワークの設置とはトラフィック分散などの方面をしていたもの
で、VBをあまり深く理解してないんです。

どなたかお知恵を貸して頂ければ幸いです。よろしくお願いします。
どのようなコードを書いたのか提示していただければ、助けようと思ってくださる方もいらっしゃるのではないかと思いますが。(これではいったい何のクラスを使ったのかさえ分かりませんし...。)
レスが遅くなって大変申し訳ありません。

何分、海外出張中のためネット環境が非常に悪くて接続が満足に出来ない状態なもので・・

コードを記述します。

クライアント側:
Public Class AsyncTCPClient

' The response from the remote device.
'Private response As [String] = [String].Empty
Private response() As Byte
Private tcpClient As Socket
Private state As StateStreamObject
Private m_SendTimeOut As Integer = 10000
Private m_ReceiveTimeOut As Integer = 10000

Public Property SendTimeOut() As Integer
Get
SendTimeOut = m_SendTimeOut
End Get
Set(ByVal Value As Integer)
If Value >= 0 Then
m_SendTimeOut = Value
End If
End Set
End Property

Public Property ReceiveTimeOut() As Integer
Get
ReceiveTimeOut = m_ReceiveTimeOut
End Get
Set(ByVal Value As Integer)
If Value >= 0 Then
m_ReceiveTimeOut = Value
End If
End Set
End Property


Public Sub New()
state = New StateStreamObject()
End Sub 'New
Public Sub New(ByVal BufferSize As Integer)
state = New StateStreamObject(BufferSize)
End Sub

Public Function Connect(ByVal host As String, ByVal port As Integer) As Boolean
Try
Dim ipHostInfo As IPHostEntry = Dns.Resolve(host)
Dim ipAddress As IPAddress = ipHostInfo.AddressList(0)
Dim remoteEP As New IPEndPoint(ipAddress, port)

' Create a TCP/IP socket.
If Not (tcpClient Is Nothing) Then
tcpClient = Nothing
End If
tcpClient = New Socket(AddressFamily.InterNetwork, _
SocketType.Stream, ProtocolType.Tcp)

tcpClient.Connect(remoteEP)
Connect = True
Catch e As Exception
ErrorLog(e, EventLogEntryType.Error)
End Try
End Function 'Connect

Public Function Send(ByVal bytedata() As Byte) As Boolean
Try
' Set TimeOut
tcpClient.SetSocketOption(SocketOptionLevel.Socket, _
SocketOptionName.SendTimeout, m_SendTimeOut)

' Data Send
tcpClient.Send(bytedata, bytedata.Length, SocketFlags.None)
Send = True
Catch e As Exception
ErrorLog(e, EventLogEntryType.Error)
End Try
End Function 'Send

Public Function Receive(ByRef Buffer As TcpBuffer) As Boolean
Try
Dim intRcvByte As Integer
Dim bytBuffer(1024) As Byte
Buffer.intCount = 0
ReDim Buffer.bytData(0)

' Set TimeOut
tcpClient.SetSocketOption(SocketOptionLevel.Socket, _
SocketOptionName.ReceiveTimeout, m_ReceiveTimeOut)
Do
' Data Receive
intRcvByte = tcpClient.Receive(bytBuffer)
If intRcvByte > 0 Then
ReDim Preserve Buffer.bytData(Buffer.intCount + intRcvByte - 1)
Dim i As Integer
For i = 0 To intRcvByte - 1
Buffer.bytData(Buffer.intCount) = bytBuffer(i)
Buffer.intCount += 1
Next
Receive = True
End If
Debug.WriteLine("Availabel: " & tcpClient.Available.ToString)
Loop While tcpClient.Available > 0
Catch e As Exception
ErrorLog(e, EventLogEntryType.Error)
End Try
End Function 'Receive

Public Sub Close()
Try
' Release the socket.
If Not (tcpClient Is Nothing) Then
tcpClient.Close()
tcpClient = Nothing
End If
Catch e As Exception
ErrorLog(e, EventLogEntryType.Error)
End Try
End Sub 'Close
End Class
一回のレスで記述できないので、2回に分けて掲載します。

サーバ側コード:
Public Class AsyncTCPServer

' The response from the remote device.
'Private response As [String] = [String].Empty
Private response() As Byte
Private tcpServer As Socket
Private state As StateStreamObject
Private m_SendTimeOut As Integer = 10000
Private m_ReceiveTimeOut As Integer = 10000

Event Connected()

Public Property SendTimeOut() As Integer
Get
SendTimeOut = m_SendTimeOut
End Get
Set(ByVal Value As Integer)
If Value >= 0 Then
m_SendTimeOut = Value
End If
End Set
End Property

Public Property ReceiveTimeOut() As Integer
Get
ReceiveTimeOut = m_ReceiveTimeOut
End Get
Set(ByVal Value As Integer)
If Value >= 0 Then
m_ReceiveTimeOut = Value
End If
End Set
End Property


Public Sub New()
state = New StateStreamObject()
End Sub 'New
Public Sub New(ByVal BufferSize As Integer)
state = New StateStreamObject(BufferSize)
End Sub

Public Function Listen(ByVal port As Integer) As Boolean
Try
' Data buffer for incoming data.
Dim bytes() As Byte = New [Byte](1024) {}

' Establish the local endpoint for the socket.
' The DNS name of the computer
' running the listener is "host.contoso.com".
Dim ipHostInfo As IPHostEntry = Dns.Resolve(Dns.GetHostName())
Dim ipAddress As IPAddress = ipHostInfo.AddressList(0)
Dim localEndPoint As New IPEndPoint(ipAddress, port)

' Intializes a TCP/IP socket.
If Not (tcpServer Is Nothing) Then
tcpServer = Nothing
End If
tcpServer = New Socket(AddressFamily.InterNetwork, _
SocketType.Stream, ProtocolType.Tcp)

tcpServer.Bind(localEndPoint)
tcpServer.Listen(100)

Listen = True
Catch e As Exception
ErrorLog(e, EventLogEntryType.Error)
End Try

End Function 'Listen

Public Function BeginAccept() As Boolean
Try
' Start an asynchronous socket to listen for connections.
tcpServer.BeginAccept(New AsyncCallback(AddressOf AcceptCallback), tcpServer)
BeginAccept = True
Catch e As Exception
ErrorLog(e, EventLogEntryType.Error)
End Try
End Function

Public Function Send(ByVal bytedata() As Byte) As Boolean
Try
' Set TimeOut
state.workSocket.SetSocketOption(SocketOptionLevel.Socket, _
SocketOptionName.SendTimeout, m_SendTimeOut)

' Data Send
state.workSocket.Send(bytedata, bytedata.Length, SocketFlags.None)
Send = True
Catch e As Exception
ErrorLog(e, EventLogEntryType.Error)
End Try
End Function 'Send

Public Function Receive(ByRef Buffer As TcpBuffer) As Boolean
Try
Dim intRcvByte As Integer
Dim bytBuffer(1024) As Byte
Buffer.intCount = 0
ReDim Buffer.bytData(0)

' Set TimeOut
state.workSocket.SetSocketOption(SocketOptionLevel.Socket, _
SocketOptionName.ReceiveTimeout, m_ReceiveTimeOut)
Do
' Data Receive
intRcvByte = state.workSocket.Receive(bytBuffer)
If intRcvByte > 0 Then
ReDim Preserve Buffer.bytData(Buffer.intCount + intRcvByte - 1)
Dim i As Integer
For i = 0 To intRcvByte - 1
Buffer.bytData(Buffer.intCount) = bytBuffer(i)
Buffer.intCount += 1
Next
Receive = True
End If
Debug.WriteLine("Availabel: " & state.workSocket.Available.ToString)
Loop While state.workSocket.Available > 0
Catch e As Exception
ErrorLog(e, EventLogEntryType.Error)
End Try
End Function 'Receive

Public Sub Close()
Try
' Release the socket.
If Not (state.workSocket Is Nothing) Then
state.workSocket.Close()
state.workSocket = Nothing
End If
Catch e As Exception
ErrorLog(e, EventLogEntryType.Error)
End Try
End Sub 'Close

Public Sub ServerClose()
Try
' Release the socket.
If Not (tcpServer Is Nothing) Then
tcpServer.Close()
tcpServer = Nothing
End If
Catch e As Exception
ErrorLog(e, EventLogEntryType.Error)
End Try
End Sub 'ServerClose

Public Sub AcceptCallback(ByVal ar As IAsyncResult)
Try
' Get the socket that handles the client request.
Dim listener As Socket = CType(ar.AsyncState, Socket)

If Not (listener Is Nothing) And Not (tcpServer Is Nothing) Then
state.workSocket = listener.EndAccept(ar)

RaiseEvent Connected()
End If

Catch e As Exception
ErrorLog(e, EventLogEntryType.Error)
End Try
End Sub 'AcceptCallback
End Class 'AsyncTCPServer

以上です。処理としては、クライアント側から接続してデータを送信。送信したデータをサーバが受取ったらヘッダにFTP_OKを入れてクライアントに返す。データの送信が終わったらサーバ側から切断するようになっています。(ここの考え方自体があまり良くないのですが、システム上これでないとダメなのもので・・)

どなたか、よい回避方法などありましたらご教授ください。よろしくお願いします。
自己レスですいません。なんとか送信できない問題を解決しました。

みなさんのお手を煩わせて申し訳ありませんでした。

また、何かありましたらよろしくお願いいたします。
解決済み!

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