none
Socket通信 networkstreamを用いた際に接続クライアントを1個→2個に増やすとサーバー側の受信速度が遅くなる件 RRS feed

  • 質問

  • 環境:VisualStudio.net VB2010

    業務用ソフトを開発中ですが表題の問題が発生しているためソケット通信にお詳しい方がいらっしゃいましたら何卒お知恵をお貸し願えませんでしょうか?

    ネット上の情報をもとにTCPListenerクラスを用いた複数クライアントからの同時接続受け入れ可能なサーバーソフトを

    開発しております。クライアントから10~60MB程度の画像データをByte型に変換して送信する仕様となっております。

    その際、接続クライアントが1個の場合はほぼ理論値通りの転送速度(1000Mbpsに近いもの)が得られておりますが、

    接続クライアントを2個に増やして両クライアントから連続して画像データを送信すると、どちらの画像データの受信速度も

    クライアント1個送信時に4ms程度のものが400msに増えてしまいます。接続ポートを分ければよいのでは?と思い

    クライアントごとに50000、50001 とポートを分けて接続しましたが結果は変わりませんでした。

    クライアントが2個以上接続時にもデータの送信速度を落とさないようにするためにはどのような設定をすればよいのでしょうか?

    参考までに下記にソース部を記載します。

    ①クライアント接続を待っている部分

     '/** セカンドスレッドで実行されるサーバーのListen **"
        'サーバーのListen 
        Private Sub ServerListen(aport As Integer)
            'TcpListenerを作成 
            Listener = New TcpListener(IPAddress.Any, Integer.Parse(aport))
            Listener.Start()
            ' クライアントの接続を受けるための永久ループ 
            Try
                Do
                    ' Listener.AcceptSocketは同期メソドで接続要求が有るまで 
                    '値を返さずここで待機します 
                    ' 新しい接続要求ががあると接続を許可して 
                    ' 新しいソケットを返します 
                    Dim socketForClient As Socket = Listener.AcceptSocket()
                    'クライアント毎の接続とフォームのインスタンスを渡す 
                    Dim handler As New ClientHandler(socketForClient, Me)
                    'ListクラスにClientHandlerのインスタンスを保持します 
                    Me.BeginInvoke(New dlgsetList(AddressOf Me.addNewClient), New Object() {handler})
                    '読み込みを開始 
                    handler.StartRead()
                Loop While True
            End Try
        End Sub

    ②接続された場合のコンストラクタ部

         'クラスのコンストラクタ 
            Public Sub New(ByVal socketForClient As Socket, ByVal _FomServer As FormMain)
                '呼び出し側のSocketを保持 
                socket = socketForClient
                '呼び出し側のフォームのインスタンスを保持 
                formMaineServer = _FomServer
                '読み込み用のバッファ 
                buffer = New Byte(1024) {}
                'socketの読み書き用のstreamを作成します 
                networkStream = New NetworkStream(socketForClient)
                '読み込み完了時にCLRから呼ばれるメソド 
                callbackRead = New AsyncCallback(AddressOf Me.OnReadComplete)
                '書き込み完了時にCLRから呼ばれるメソド 
                callbackWrite = New AsyncCallback(AddressOf Me.OnWriteComplete)
          

            End Sub

       

    ③実際のデータ受信部

         Public Sub StartRead()
                networkStream.BeginRead(buffer, 0, buffer.Length, callbackRead, Nothing)
            End Sub

    ④データ受信

     
      'networkStream.BeginReadの別スレッドから、読み込み完了時 
            '又はクライアント切断時にコールバックされます。 
            Private Sub OnReadComplete(ByVal ar As IAsyncResult)
                Try
                    '受信文字をStreamから読み込みます 
                    If networkStream Is Nothing Then
                        Exit Sub
                    End If
                    '受信バイト数が返る 
                    Dim bytesRead As Integer = networkStream.EndRead(ar)
                    If bytesRead > 0 Then
                        getData(buffer, bytesRead)
                        '次の受信を待つ 
                        networkStream.BeginRead(buffer, 0, buffer.Length, callbackRead, Nothing)
                    Else
                        '終了ボタンが押され場合はここに落ちる 
                        'クライアントのList<T>からの削除 
                        formMaineServer.Invoke(New dlgsetList(AddressOf formMaineServer.deleteClient), New Object() {Me})
                        networkStream.Close()
                        socket.Close()
                        networkStream = Nothing
                        Thread.Sleep(20) 'これを入れないとNullReferenceExceptionが起きる
                        socket = Nothing
                    End If
             
                Catch ex As Exception
                    'エラーログの書き込み 
                    formMaineServer.Invoke(New dlgWriteLog(AddressOf formMaineServer.WriteLog), New Object() {"受信エラーが起こりました " & ex.ToString()})
                End Try
            End Sub

    ちなみに本サーバーアプリを2個起動させて2個クライアントソフトをそれぞれのサーバーアプリに接続すると

    データ送信時間は遅くならないことも確認されておりますが、ソフトの使用上、どうしてもサーバーアプリを1個に

    まとめる必要がございます。

    専門家、有識者の方々のお知恵を拝借したく、どうぞよろしくお願いいたします。

    2017年7月7日 8:56

回答

  • 1Gbpsのイーサネットで効率100%であったとしても

     1[Gbps] = 1000[Mbps] = 125[MByte/sec] 
     10MBを転送するのに必要な時間 10[MByte] / 125[MByte/sec] = 0.08[sec]
     60MBを転送するのに必要な時間 60[MByte] / 125[MByte/sec] = 0.48[sec]

    となります。実効速度は100%にならないので、もっと時間がかかるはずです。
    さらに、2クライアントが同時接続すれば1クライアントが占有できるのは半分になるので時間は倍になりますし、もっと増えればもっと時間がかかります。
    つまり、4ミリ秒で転送ができているのがあり得ないです。

    時間の計測をどのように行っているか示されていないですが、そのあたりのやり方を見直してみては?

    以下、提示されていない部分を推測して書きなおしてみる

    Imports System.Net
    Imports System.Net.Sockets
    
    Public Class FormMain
        Private Listener As TcpListener
        Private address As TextBox
        Private lsb As ListBox
        Private log As TextBox
        Private clientCount As Integer
        Private totalStart As DateTime
    
        Sub New()
            InitializeComponent()
    
            Dim tip As New ToolTip
    
            address = New TextBox() With {.Left = 10, .Top = 10, .Width = 100, .Text = "127.0.0.1"}
            tip.SetToolTip(address, "サーバーアドレス")
            Me.Controls.Add(address)
    
            Dim port As New NumericUpDown() With {.Minimum = 1, .Maximum = 65535, .Value = 10000, .Left = 10, .Top = Me.address.Bottom + 5, .Width = 100}
            tip.SetToolTip(port, "サーバーポート")
            Me.Controls.Add(port)
    
            Dim btnStartServer As New Button With {.Text = "Server", .Left = 10, .Top = port.Bottom + 5}
            AddHandler btnStartServer.Click, _
                Sub(s, e)
                    ServerListen(CInt(port.Value))
                    CType(s, Button).Enabled = False
                End Sub
    
            Me.Controls.Add(btnStartServer)
    
            Dim count As New NumericUpDown() With {.Minimum = 1, .Maximum = 5, .Value = 2, .Left = 150, .Top = port.Top, .Width = 50}
            tip.SetToolTip(count, "同時接続数")
            Me.Controls.Add(count)
    
            Dim size As New NumericUpDown() With {.Minimum = 1, .Maximum = 100, .Value = 60, .Left = count.Right + 5, .Top = count.Top, .Width = 50}
            tip.SetToolTip(size, "転送サイズ(MB)")
            Me.Controls.Add(size)
    
            Dim btnClient As New Button() With {.Text = "Client", .Left = 150, .Top = btnStartServer.Top}
            AddHandler btnClient.Click, _
                Sub(s, e)
                    Dim serverAddress As IPAddress = Nothing
                    Try
                        serverAddress = IPAddress.Parse(address.Text)
                    Catch ex As Exception
                        MessageBox.Show(ex.Message, "", MessageBoxButtons.OK, MessageBoxIcon.Error)
                        Exit Sub
                    End Try
                    StartClient(serverAddress, CInt(port.Value), CInt(count.Value), CByte(size.Value))
                End Sub
            Me.Controls.Add(btnClient)
    
            lsb = New ListBox() With {.Left = 0, .Top = btnStartServer.Bottom + 5, .Height = 50, .Width = Me.ClientSize.Width, .Anchor = CType(&HD, AnchorStyles), .IntegralHeight = False}
            Me.Controls.Add(lsb)
    
            log = New TextBox() With {.Left = 0, .Top = lsb.Bottom + 5, .Width = Me.ClientSize.Width, .Height = Me.ClientSize.Height - .Top, .Anchor = CType(&HF, AnchorStyles), .Multiline = True, .ScrollBars = ScrollBars.Both}
            Me.Controls.Add(log)
        End Sub
        Friend Sub addNewClient(ByVal ch As ClientHandler)
            lsb.Items.Add(ch)
        End Sub
        Friend Sub deleteClient(ByVal ch As ClientHandler)
            lsb.Items.Remove(ch)
        End Sub
        Friend Sub WriteLog(ByVal msg As String)
    
            If (Me.InvokeRequired) Then
                Me.BeginInvoke(Sub() WriteLog(msg))
            Else
                System.Diagnostics.Debug.WriteLine(msg)
                log.AppendText(msg + vbCrLf)
            End If
        End Sub
    
        Private Sub ServerListen(portNumber As Integer)
            Dim thread As System.Threading.Thread
            thread = New System.Threading.Thread _
                (Sub()
                     Me.Listener = New TcpListener(IPAddress.Any, portNumber)
                     Me.Listener.Start()
                     Try
                         Do
                             Dim socketForClient As Socket = Listener.AcceptSocket()
                             Dim handler As New ClientHandler(socketForClient)
                             AddHandler handler.Closed, _
                                 Sub(s, e)
                                     Me.BeginInvoke _
                                         (Sub()
                                              Dim ela As TimeSpan = (handler.EndTime - handler.StartTime)
                                              Dim mbps As Double = handler.Length * 8 / ela.TotalSeconds / 1024 / 1024
    
                                              WriteLog(String.Format("{0,5} > {1:HH:mm:ss.fff} - {2:HH:mm:ss.fff} # {3,5:0}ms # {4,8:f3}Mbps", handler.Port, handler.StartTime, handler.EndTime, ela.TotalMilliseconds, mbps))
                                              deleteClient(handler)
    
                                              If (System.Threading.Interlocked.Decrement(Me.clientCount) = 0) Then
                                                  WriteLog(String.Format("{0:0}ms", (handler.EndTime - Me.totalStart).TotalMilliseconds))
                                              End If
                                          End Sub)
                                 End Sub
    
                             Me.BeginInvoke(Sub()
                                                addNewClient(handler)
                                            End Sub)
    
                             handler.StartRead()
                         Loop While True
                     Catch ex As Exception
                         Me.BeginInvoke(Sub() MessageBox.Show(ex.Message, "", MessageBoxButtons.OK, MessageBoxIcon.Exclamation))
                     End Try
                 End Sub)
            thread.IsBackground = True
            thread.Start()
    
        End Sub
    
        Private Sub StartClient(ByVal address As IPAddress, ByVal portNumber As Integer, ByVal count As Integer, ByVal megabyte As Byte)
            Me.log.Clear()
            Me.clientCount = 0
            Dim ep As New IPEndPoint(address, portNumber)
    
            Dim data() As Byte
            data = New Byte(1024 * 1024 * megabyte) {}
            Dim rnd As New Random
    
            rnd.NextBytes(data)
    
            For i As Integer = 1 To count
                Dim thread As New System.Threading.Thread _
                    (Sub()
                         Dim start As DateTime = DateTime.Now
                         If (System.Threading.Interlocked.Increment(Me.clientCount) = 1) Then
                             Me.totalStart = start
                         End If
                         Dim client As New TcpClient()
                         Try
                             client.Connect(ep)
                         Catch ex As Exception
                             MessageBox.Show(ex.Message)
                             Exit Sub
                         End Try
    
                         WriteLog(String.Format("{0,5} < {1:HH:mm:ss.fff}", CType(client.Client.LocalEndPoint, IPEndPoint).Port, start))
    
                         Dim stream = client.GetStream()
                         stream.Write(data, 0, data.Length)
                         stream.Close()
                     End Sub)
                thread.IsBackground = True
                thread.Start()
            Next
    
        End Sub
    
    End Class
    
    Public Class ExceptionEventArgs
        Inherits EventArgs
        Public Message As String
        Public Exception As Exception
    End Class
    
    Friend Class ClientHandler
        Public Socket As Socket
        Private BUffer() As Byte
        Private NetworkStream As NetworkStream
        Private callbackRead As AsyncCallback
        Private callbackWrite As AsyncCallback
        Public Port As Integer
    
        Public Event ReadError As EventHandler(Of ExceptionEventArgs)
        Public Event Closed As EventHandler(Of EventArgs)
    
        Public Property StartTime As DateTime
        Public Property EndTime As DateTime
    
    
        Public Sub New(ByVal socketForClient As Socket)
            StartTime = DateTime.Now
            EndTime = DateTime.MaxValue
    
            Socket = socketForClient
            BUffer = New Byte(1024) {}
            NetworkStream = New NetworkStream(socketForClient)
            callbackRead = New AsyncCallback(AddressOf Me.OnReadComplete)
            callbackWrite = New AsyncCallback(AddressOf Me.OnWriteComplete)
    
            Port = CType(socketForClient.RemoteEndPoint, IPEndPoint).Port
        End Sub
    
        Public Sub StartRead()
            NetworkStream.BeginRead(BUffer, 0, BUffer.Length, callbackRead, Nothing)
        End Sub
    
        Private Sub OnReadComplete(ByVal ar As IAsyncResult)
            Try
                If NetworkStream Is Nothing Then
                    Exit Sub
                End If
    
                Dim bytesRead As Integer = NetworkStream.EndRead(ar)
                If bytesRead > 0 Then
                    getData(BUffer, bytesRead)
                    NetworkStream.BeginRead(BUffer, 0, BUffer.Length, callbackRead, Nothing)
                Else
    
                    NetworkStream.Close()
                    Socket.Close()
                    Socket.Dispose()
                    NetworkStream = Nothing
                    'System.Threading.Thread.Sleep(20) 'これを入れないとNullReferenceExceptionが起きる
                    Socket = Nothing
    
                    EndTime = DateTime.Now
                    RaiseEvent Closed(Me, EventArgs.Empty)
                End If
    
            Catch ex As Exception
                RaiseEvent ReadError(Me, New ExceptionEventArgs() With {.Exception = ex, .Message = "受信エラーが起こりました"})
            End Try
        End Sub
    
        Public Property Length As Long
    
        Private Sub getData(ByRef buffer As Byte(), ByVal count As Integer)
            Length = Length + count
        End Sub
        Private Sub OnWriteComplete(ByVal ar As IAsyncResult)
        End Sub
    End Class

    #テスト環境では1クライアントだと800Mbps位、2クライアントで900Mbps位


    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    2017年7月8日 9:43

すべての返信

  • 1Gbpsのイーサネットで効率100%であったとしても

     1[Gbps] = 1000[Mbps] = 125[MByte/sec] 
     10MBを転送するのに必要な時間 10[MByte] / 125[MByte/sec] = 0.08[sec]
     60MBを転送するのに必要な時間 60[MByte] / 125[MByte/sec] = 0.48[sec]

    となります。実効速度は100%にならないので、もっと時間がかかるはずです。
    さらに、2クライアントが同時接続すれば1クライアントが占有できるのは半分になるので時間は倍になりますし、もっと増えればもっと時間がかかります。
    つまり、4ミリ秒で転送ができているのがあり得ないです。

    時間の計測をどのように行っているか示されていないですが、そのあたりのやり方を見直してみては?

    以下、提示されていない部分を推測して書きなおしてみる

    Imports System.Net
    Imports System.Net.Sockets
    
    Public Class FormMain
        Private Listener As TcpListener
        Private address As TextBox
        Private lsb As ListBox
        Private log As TextBox
        Private clientCount As Integer
        Private totalStart As DateTime
    
        Sub New()
            InitializeComponent()
    
            Dim tip As New ToolTip
    
            address = New TextBox() With {.Left = 10, .Top = 10, .Width = 100, .Text = "127.0.0.1"}
            tip.SetToolTip(address, "サーバーアドレス")
            Me.Controls.Add(address)
    
            Dim port As New NumericUpDown() With {.Minimum = 1, .Maximum = 65535, .Value = 10000, .Left = 10, .Top = Me.address.Bottom + 5, .Width = 100}
            tip.SetToolTip(port, "サーバーポート")
            Me.Controls.Add(port)
    
            Dim btnStartServer As New Button With {.Text = "Server", .Left = 10, .Top = port.Bottom + 5}
            AddHandler btnStartServer.Click, _
                Sub(s, e)
                    ServerListen(CInt(port.Value))
                    CType(s, Button).Enabled = False
                End Sub
    
            Me.Controls.Add(btnStartServer)
    
            Dim count As New NumericUpDown() With {.Minimum = 1, .Maximum = 5, .Value = 2, .Left = 150, .Top = port.Top, .Width = 50}
            tip.SetToolTip(count, "同時接続数")
            Me.Controls.Add(count)
    
            Dim size As New NumericUpDown() With {.Minimum = 1, .Maximum = 100, .Value = 60, .Left = count.Right + 5, .Top = count.Top, .Width = 50}
            tip.SetToolTip(size, "転送サイズ(MB)")
            Me.Controls.Add(size)
    
            Dim btnClient As New Button() With {.Text = "Client", .Left = 150, .Top = btnStartServer.Top}
            AddHandler btnClient.Click, _
                Sub(s, e)
                    Dim serverAddress As IPAddress = Nothing
                    Try
                        serverAddress = IPAddress.Parse(address.Text)
                    Catch ex As Exception
                        MessageBox.Show(ex.Message, "", MessageBoxButtons.OK, MessageBoxIcon.Error)
                        Exit Sub
                    End Try
                    StartClient(serverAddress, CInt(port.Value), CInt(count.Value), CByte(size.Value))
                End Sub
            Me.Controls.Add(btnClient)
    
            lsb = New ListBox() With {.Left = 0, .Top = btnStartServer.Bottom + 5, .Height = 50, .Width = Me.ClientSize.Width, .Anchor = CType(&HD, AnchorStyles), .IntegralHeight = False}
            Me.Controls.Add(lsb)
    
            log = New TextBox() With {.Left = 0, .Top = lsb.Bottom + 5, .Width = Me.ClientSize.Width, .Height = Me.ClientSize.Height - .Top, .Anchor = CType(&HF, AnchorStyles), .Multiline = True, .ScrollBars = ScrollBars.Both}
            Me.Controls.Add(log)
        End Sub
        Friend Sub addNewClient(ByVal ch As ClientHandler)
            lsb.Items.Add(ch)
        End Sub
        Friend Sub deleteClient(ByVal ch As ClientHandler)
            lsb.Items.Remove(ch)
        End Sub
        Friend Sub WriteLog(ByVal msg As String)
    
            If (Me.InvokeRequired) Then
                Me.BeginInvoke(Sub() WriteLog(msg))
            Else
                System.Diagnostics.Debug.WriteLine(msg)
                log.AppendText(msg + vbCrLf)
            End If
        End Sub
    
        Private Sub ServerListen(portNumber As Integer)
            Dim thread As System.Threading.Thread
            thread = New System.Threading.Thread _
                (Sub()
                     Me.Listener = New TcpListener(IPAddress.Any, portNumber)
                     Me.Listener.Start()
                     Try
                         Do
                             Dim socketForClient As Socket = Listener.AcceptSocket()
                             Dim handler As New ClientHandler(socketForClient)
                             AddHandler handler.Closed, _
                                 Sub(s, e)
                                     Me.BeginInvoke _
                                         (Sub()
                                              Dim ela As TimeSpan = (handler.EndTime - handler.StartTime)
                                              Dim mbps As Double = handler.Length * 8 / ela.TotalSeconds / 1024 / 1024
    
                                              WriteLog(String.Format("{0,5} > {1:HH:mm:ss.fff} - {2:HH:mm:ss.fff} # {3,5:0}ms # {4,8:f3}Mbps", handler.Port, handler.StartTime, handler.EndTime, ela.TotalMilliseconds, mbps))
                                              deleteClient(handler)
    
                                              If (System.Threading.Interlocked.Decrement(Me.clientCount) = 0) Then
                                                  WriteLog(String.Format("{0:0}ms", (handler.EndTime - Me.totalStart).TotalMilliseconds))
                                              End If
                                          End Sub)
                                 End Sub
    
                             Me.BeginInvoke(Sub()
                                                addNewClient(handler)
                                            End Sub)
    
                             handler.StartRead()
                         Loop While True
                     Catch ex As Exception
                         Me.BeginInvoke(Sub() MessageBox.Show(ex.Message, "", MessageBoxButtons.OK, MessageBoxIcon.Exclamation))
                     End Try
                 End Sub)
            thread.IsBackground = True
            thread.Start()
    
        End Sub
    
        Private Sub StartClient(ByVal address As IPAddress, ByVal portNumber As Integer, ByVal count As Integer, ByVal megabyte As Byte)
            Me.log.Clear()
            Me.clientCount = 0
            Dim ep As New IPEndPoint(address, portNumber)
    
            Dim data() As Byte
            data = New Byte(1024 * 1024 * megabyte) {}
            Dim rnd As New Random
    
            rnd.NextBytes(data)
    
            For i As Integer = 1 To count
                Dim thread As New System.Threading.Thread _
                    (Sub()
                         Dim start As DateTime = DateTime.Now
                         If (System.Threading.Interlocked.Increment(Me.clientCount) = 1) Then
                             Me.totalStart = start
                         End If
                         Dim client As New TcpClient()
                         Try
                             client.Connect(ep)
                         Catch ex As Exception
                             MessageBox.Show(ex.Message)
                             Exit Sub
                         End Try
    
                         WriteLog(String.Format("{0,5} < {1:HH:mm:ss.fff}", CType(client.Client.LocalEndPoint, IPEndPoint).Port, start))
    
                         Dim stream = client.GetStream()
                         stream.Write(data, 0, data.Length)
                         stream.Close()
                     End Sub)
                thread.IsBackground = True
                thread.Start()
            Next
    
        End Sub
    
    End Class
    
    Public Class ExceptionEventArgs
        Inherits EventArgs
        Public Message As String
        Public Exception As Exception
    End Class
    
    Friend Class ClientHandler
        Public Socket As Socket
        Private BUffer() As Byte
        Private NetworkStream As NetworkStream
        Private callbackRead As AsyncCallback
        Private callbackWrite As AsyncCallback
        Public Port As Integer
    
        Public Event ReadError As EventHandler(Of ExceptionEventArgs)
        Public Event Closed As EventHandler(Of EventArgs)
    
        Public Property StartTime As DateTime
        Public Property EndTime As DateTime
    
    
        Public Sub New(ByVal socketForClient As Socket)
            StartTime = DateTime.Now
            EndTime = DateTime.MaxValue
    
            Socket = socketForClient
            BUffer = New Byte(1024) {}
            NetworkStream = New NetworkStream(socketForClient)
            callbackRead = New AsyncCallback(AddressOf Me.OnReadComplete)
            callbackWrite = New AsyncCallback(AddressOf Me.OnWriteComplete)
    
            Port = CType(socketForClient.RemoteEndPoint, IPEndPoint).Port
        End Sub
    
        Public Sub StartRead()
            NetworkStream.BeginRead(BUffer, 0, BUffer.Length, callbackRead, Nothing)
        End Sub
    
        Private Sub OnReadComplete(ByVal ar As IAsyncResult)
            Try
                If NetworkStream Is Nothing Then
                    Exit Sub
                End If
    
                Dim bytesRead As Integer = NetworkStream.EndRead(ar)
                If bytesRead > 0 Then
                    getData(BUffer, bytesRead)
                    NetworkStream.BeginRead(BUffer, 0, BUffer.Length, callbackRead, Nothing)
                Else
    
                    NetworkStream.Close()
                    Socket.Close()
                    Socket.Dispose()
                    NetworkStream = Nothing
                    'System.Threading.Thread.Sleep(20) 'これを入れないとNullReferenceExceptionが起きる
                    Socket = Nothing
    
                    EndTime = DateTime.Now
                    RaiseEvent Closed(Me, EventArgs.Empty)
                End If
    
            Catch ex As Exception
                RaiseEvent ReadError(Me, New ExceptionEventArgs() With {.Exception = ex, .Message = "受信エラーが起こりました"})
            End Try
        End Sub
    
        Public Property Length As Long
    
        Private Sub getData(ByRef buffer As Byte(), ByVal count As Integer)
            Length = Length + count
        End Sub
        Private Sub OnWriteComplete(ByVal ar As IAsyncResult)
        End Sub
    End Class

    #テスト環境では1クライアントだと800Mbps位、2クライアントで900Mbps位


    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    2017年7月8日 9:43
  • bufferのサイズがちょっと小さいかな、という感じもします(ふつうのEthenerのパケットは1400バイトくらいあるので。1MByteとっても大丈夫ではないでしょうか)。
    おおむね、提示されているコードにそれほど問題はないと思います。
    ただ、提示されていない、具体的にはgetDataの実装で、たとえばロックを獲得しているとか、メインウインドウへBeginInvokeしているとか、詰まる原因があるのでは、と思います。

    2017年7月8日 10:30
  • Thread.Sleep(20) 'これを入れないとNullReferenceExceptionが起きる

    苦労されている形跡が見えます。環境をVisual Studio 2012以降かつ.NET Framework 4.5以降にアップデートされますと、Async および Await を使用した非同期プログラミングを利用できます。AsyncCallbackの苦労が嘘のように解消され、パフォーマンスが向上しますので、こちらを推奨します。
    # ちなみに.NET 4.0~4.5.1はサポート終了済みです。

    .NET 2.0 SP1にてソケット パフォーマンスの強化が行われていますが、今回の質問ではこちらを使用しなくても十分なパフォーマンスを得られる領域の問題と思われますので、紹介までにとどめます。

    2017年7月8日 10:54
  • gekka様

    サンプルソースと丁寧なご返信、誠にありがとうございました。

    ご指摘通り、4msはこちらの間違いでした。転送画像が300KB程度の時の話でした。失礼いたしました。

    追加で質問させて頂きたいのですが、0ご提供いただいたサンプルソフト実行時に気になった点なのですが、例えばクライアントソフト数1個、データ60MBで転送をすると500Mbps程度の速さに対して、ソフト数を2個以上にすると900Mbpsに早くなるのは何故なのでしょうか?

    2017年7月19日 1:21
  • jzkey様
    >getDataの実装で、たとえばロックを獲得しているとか、メインウインドウへBeginInvokeしているとか、詰まる原因があるのでは、と思います。
    →ご指摘通り、getDataの中でBeginInvokeを実行していました。その関数が実行されている時間中に他のスレッドからのアクセスを拒否しているためにその分の待ち時間が発生しておりました。ですのでBeginInvokeをやめて通常の関数の形での呼び出しにすればうまくいくのですが、BeginInvoke内のUI要素へのアクセス時にエラーが発生してしまうようになりました。ロックされる時間を最小限にするためにUI要素にアクセスする関数部位(エラーが発生する箇所)だけにSyncLock?処理を入れましたがうまくいかないようで相変わらずエラーが発生しており作業が中断しております。UI要素へアクセスする方法はDLLで提供されている機能のためその使用を避けることはできない状態です。やはりSynclockを理解して使用するしかないのでしょうか?参考までにサンプルソースを添付いたします。

    Friend Shared Function AccessData(ByVal a As toto.TT)

            Try

               
                'SyncLock (a)          '→入れてみましたが効果なし

                Dim bbb As toto.Ibbb

                bbb = a.getImage(index)'→ここでエラーが発生
          
                'End SyncLock     '→入れてみましたが効果なし

            Catch ex As Exception
                Console.WriteLine(ex.Message)
                Throw
            End Try
           
    end Function

    2017年7月19日 1:42
  • 佐祐理様

    情報のご提供ありがとうございます。教えて頂いた方法ですが当方には難しいようです。ソケット通信を本方法で書き換えられたサンプル等はどこかにございますでしょうか?

    2017年7月19日 1:45