2011-10-15 2 views
0

한 번에 여러 클라이언트와 통신하는 TCP 서버를 만들었지 만 안정적으로 만들 수없는 것처럼 보입니다. 클라이언트 중 하나가 서버에 100 개의 패킷을 전송하면 서버는 그 중 일부만 수신합니다.VB.NET 비동기 소켓 패킷이 손실 됨

Here's the client code in PasteBin. 클라이언트가 서버에 연결하는 방법을 보여주고 For 루프에서 100 개의 메시지를 서버로 보냅니다.

And here's how the server handles the connection. 길이가 수백 줄이기 때문에 전체 소스를 붙여 넣을 수는 없으므로 필요한 부분이없는 경우 알려 주시면 업로드하겠습니다.

답변

1

나는 또한 reddit에 대한 질문에 답변했지만, 다른 누군가가 이런 종류의 것을 찾고있는 경우에 나는 여기에 답장을 할 것이라고 생각했습니다.

서버가 읽기를 처리하는 방식에는 두 가지 문제가 있습니다. 우선, 클라이언트 객체의 생성자 :

Public Sub New(ByVal client As TcpClient) 
    'New client connects 
    Me.client = client 
    client.GetStream().BeginRead(New Byte() {0}, 0, 0, AddressOf Read, Nothing) 
End Sub 

그러면 BeginRead 당신이 콜백 메소드에 건네 줄 수있는 방법으로 데이터를 수집 할 것으로 예상; 이 경우 "읽기". 일반적으로이 비동기 작업의 "상태"를 보유 할 새 개체를 만들고이를 BeginRead의 마지막 매개 변수로 전달하면됩니다. 메서드 호출은 새로운 바이트 배열을 만드는 것이지만 메서드에 대한 마지막 인수로 전달할 참조를 보유하지 않습니다. 즉,이 호출에 의해 읽혀진 데이터는 읽은 후에 사라지게됩니다. 왜냐하면 결코 그것을 저장하는 메소드로 전달되지 않기 때문입니다. 둘째

, 당신의 읽기 동작 :

Public Sub Read(ByVal ar As IAsyncResult) 
    Dim reader As New StreamReader(client.GetStream()) 
    clientPacket &= reader.ReadLine() 
    client.GetStream().BeginRead(New Byte() {0}, 0, 0, AddressOf Read, Nothing) 
End Sub 

당신이, 당신은 클라이언트에서 더 많은 데이터를 끌어 여기에 새에서는 StreamReader를 만드는 비동기 호출에서 읽은 데이터를 전달하지 않는 때문에 . 이것은 비동기 메서드 호출이 아닙니다. reader.ReadLine() 호출은 개행 문자가 나올 때까지 차단되어 그 시점에서 데이터가 clientPacket에 추가됩니다. 위에서 언급 한 것과 동일한 문제로 BeginRead를 다시 호출하면 더 많은 데이터가 손실됩니다.

또한 스트림에서 EndRead()를 호출하여 AsyncResult 개체를 지우지 않아 비동기 작업에 대한 작업자 스레드가 CLR에서 부족 해지면 결국 자원 고갈이 발생합니다.

다음은 이러한 종류의 작업을 구현하는 방법의 예입니다. 그것은 C#에 있습니다. 왜냐하면 그것이 내가 가장 편안하다고 생각하기 때문에, 정말 미안합니다. ;)

Client Code

Server Code

난이 도움이되기를 바랍니다!

+0

감사합니다. 작동하도록하십시오! – Scyte