2011-01-31 5 views
3

TCP 프로토콜을 사용하는 .NET 소켓을 사용하는 단일 스레드 서버가 있고 Socket.Pool(), Socket.Select(), Socket.Receive()입니다. 보내려면Socket.SendAsync가 Mono/Linux에서 순서대로 전송되지 않습니다.

, 내가 사용 :

public void SendPacket(int clientid, byte[] packet) 
{ 
    clients[clientid].socket.Send(packet); 
} 

그러나 하나의 클라이언트 (전체 주 스레드를 중지)에 많은 데이터를 보낼 때 매우 느린, 그래서 나는이 그것을 대체 :

public void SendPacket(int clientid, byte[] packet) 
{ 
    using (SocketAsyncEventArgs e = new SocketAsyncEventArgs()) 
    { 
     e.SetBuffer(packet, 0, packet.Length); 
     clients[clientid].socket.SendAsync(e); 
    } 
} 

.NET (괜찮 으면 잘 모르겠다)으로 Windows에서 제대로 작동하지만 Mono가있는 Linux에서는 패킷이 삭제되거나 재정렬됩니다 (잘 모름). Socket.Send()가있는 느린 버전으로 되 돌리면 Linux에서 작동합니다. Source for whole server.

Linux에서 작동하는 non-blocking SendPacket() 함수를 작성하는 방법은 무엇입니까?

답변

0

비동기 메서드를 남용하지 않는 것이 좋습니다. 당신은 아무 것도 찾지 않을 것입니다. 스레드에 배포되는 scheuler를 대기열에 넣고, 구현 세부 사항까지 자신이 여는 문서마다 다른 것을 유지 관리하지 않는다는 사실을 무시하면됩니다.

  • 소켓 당 큐 유무 :

    가능성이 가장

    는 것입니다.
  • 이 대기열에 dasta를 쓰고 작업자 스레드가없는 경우 작업 항목 (ThreadPool)을 시작하여 스레드를 처리하십시오.

이렇게하면 순서를 유지하는 별개의 대기열이 있습니다. 하나의 스레드 만 하나의 큐/소켓을 처리합니다.

+0

대기열은 SendAsync가 내부적으로 수행하기 때문에 불필요합니다. – Marlon

+0

아, 아니. SendAsync는 OP가 경험했기 때문에 mulötipel 호출을 다중 행 스레드에 넣습니다. Quarantess가 없습니다. SendAsync에 대한 4 건의 호출이 올바른 순서로 처리됩니다. – TomTom

1

나는 귀하의 using 명세서와 귀하의 SendAsync 전화와 관련이 있다고 추측합니다. 아마도 e은 범위를 벗어나 처분 중입니다. SendAsync은 여전히 ​​버퍼를 처리하고 있습니다. 하지만이 경우 예외가 발생할 수 있습니다. 나는 정말로 짐작하고있다. using 문을 제거하고 어떻게되는지보십시오.

+0

OutOfMemoryException이 있었기 때문에'using'이 추가되었습니다. – exe

+0

BeginSend를 사용해 보셨습니까? – Marlon

+0

OK,'Socket.BeginSend'가 작동하는 것 같습니다. – exe

0

같은 문제가 있습니다. Linux와 Windows는 SendAsync와 동일한 방식으로 반응하지 않습니다. 때로는 리눅스가 데이터를 자르지 만 해결 방법이 있습니다. 우선 대기열을 사용해야합니다. SendAsync를 사용할 때마다 콜백을 확인해야합니다. e.Offset + e.BytesTransferred < e.Buffer.Length 인 경우 e.SetBuffer (e.Offset + e.BytesTransferred, e.Buffer.Length - e.BytesTransferred -e.Offset); SendAsync를 다시 호출하십시오.

모노 리눅스가 모든 데이터를 보내기 전에 완료되었다고 생각하는 이유를 알지 못합니다. 그러나 이상하게 여겨지지만 확실합니다.