비동기 메서드를 사용하는 .NET 3.5 클라이언트/서버 소켓 인터페이스가 있습니다. 클라이언트는 서버에 연결하고 응용 프로그램이 종료 될 때까지 연결이 열려 있어야합니다. 이 프로토콜은 다음과 같은 패턴으로 구성.NET 3.5 비동기 System.Net.Sockets.Socket에서 데이터 흐름을 정지시키는 것은 무엇입니까?
- 전송 STX 이
- 전송 데이터 1
- 가 ACK
- 전송 데이터 2 (더 많은 데이터하면서 5-6를 반복)
- 가 ACK 수신을받을 ACK
- 수신
- etx
위와 같이 두 개의 데이터 블록을 가진 단일 트랜잭션은 클라이언트로부터 4 개의 전송으로 구성됩니다. etx를 보낸 후에 클라이언트는 더 많은 데이터가 전송 될 때까지 기다렸다가 stx로 다음 전송을 시작합니다. 개인 교환기 간의 연결을 끊거나 각 stx/data/etx 페이로드를 연결하고 싶지 않습니다.
지금 연결 후 클라이언트는 첫 번째 stx를 보내고 하나의 ack를 얻을 수 있지만 그 후에는 더 많은 데이터를 와이어에 넣을 수 없습니다. 어느 쪽도 연결이 끊어지면 소켓은 손상되지 않습니다. 클라이언트 코드는 다음과 같이 심각하게 축약됩니다. 온라인 코드 샘플에서 일반적으로 사용 가능한 패턴을 따르고 있습니다.
private void SendReceive(string data) {
// ...
SocketAsyncEventArgs completeArgs;
completeArgs.Completed += new EventHandler<SocketAsyncEventArgs>(OnSend);
clientSocket.SendAsync(completeArgs);
// two AutoResetEvents, one for send, one for receive
if (!AutoResetEvent.WaitAll(autoSendReceiveEvents , -1))
Log("failed");
else
Log("success");
// ...
}
private void OnSend(object sender , SocketAsyncEventArgs e) {
// ...
Socket s = e.UserToken as Socket;
byte[] receiveBuffer = new byte[ 4096 ];
e.SetBuffer(receiveBuffer , 0 , receiveBuffer.Length);
e.Completed += new EventHandler<SocketAsyncEventArgs>(OnReceive);
s.ReceiveAsync(e);
// ...
}
private void OnReceive(object sender , SocketAsyncEventArgs e) {}
// ...
if (e.BytesTransferred > 0) {
Int32 bytesTransferred = e.BytesTransferred;
String received = Encoding.ASCII.GetString(e.Buffer , e.Offset , bytesTransferred);
dataReceived += received;
}
autoSendReceiveEvents[ SendOperation ].Set(); // could be moved elsewhere
autoSendReceiveEvents[ ReceiveOperation ].Set(); // releases mutexes
}
서버의 코드는 처음받는 것을 제외하고는 매우 유사하며 다음 응답을 보냅니다 - 서버가이 응답을 전송 한 후 연결을 수정 (내가 말할 수있는) 아무것도하지 않습니다. 문제는 클라이언트에서 SendReceive를 두 번째로 누르는 것입니다. 연결이 이미 이상한 상태입니다.
SocketAsyncEventArgs를 유지하고 소켓/연결 기간 동안 동일한 개체를 다시 사용하려면 클라이언트에서 무언가해야합니까? 연결 또는 지정된 교환 기간 동안 어떤 eventargs 객체가 중단되어야하는지 잘 모르겠습니다.
서버에서 데이터 수신을 계속하려면 무언가를해야합니까, 아니면하지 않으시겠습니까?
서버 설정 및 응답 처리는 다음과 같다 :
void Start() {
// ...
listenSocket.Bind(...);
listenSocket.Listen(0);
StartAccept(null); // note accept as soon as we start. OK?
mutex.WaitOne();
}
void StartAccept(SocketAsyncEventArgs acceptEventArg) {
if (acceptEventArg == null)
{
acceptEventArg = new SocketAsyncEventArgs();
acceptEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(OnAcceptCompleted);
}
Boolean willRaiseEvent = this.listenSocket.AcceptAsync(acceptEventArg);
if (!willRaiseEvent)
ProcessAccept(acceptEventArg);
// ...
}
private void OnAcceptCompleted(object sender , SocketAsyncEventArgs e) {
ProcessAccept(e);
}
private void ProcessAccept(SocketAsyncEventArgs e) {
// ...
SocketAsyncEventArgs readEventArgs = new SocketAsyncEventArgs();
readEventArgs.SetBuffer(dataBuffer , 0 , Int16.MaxValue);
readEventArgs.Completed += new EventHandler<SocketAsyncEventArgs>(OnIOCompleted);
readEventArgs.UserToken = e.AcceptSocket;
dataReceived = ""; // note server is degraded for single client/thread use
// As soon as the client is connected, post a receive to the connection.
Boolean willRaiseEvent = e.AcceptSocket.ReceiveAsync(readEventArgs);
if (!willRaiseEvent)
this.ProcessReceive(readEventArgs);
// Accept the next connection request.
this.StartAccept(e);
}
private void OnIOCompleted(object sender , SocketAsyncEventArgs e) {
// switch (e.LastOperation)
case SocketAsyncOperation.Receive:
ProcessReceive(e); // similar to client code
// operate on dataReceived here
case SocketAsyncOperation.Send:
ProcessSend(e); // similar to client code
}
// execute this when a data has been processed into a response (ack, etc)
private SendResponseToClient(string response) {
// create buffer with response
// currentEventArgs has class scope and is re-used
currentEventArgs.SetBuffer(sendBuffer , 0 , sendBuffer.Length);
Boolean willRaiseEvent = currentClient.SendAsync(currentEventArgs);
if (!willRaiseEvent)
ProcessSend(currentEventArgs);
}
닷넷 추적 나타낸다 다음 \ R \ n ABC 보낼 때
Socket#7588182::SendAsync() Socket#7588182::SendAsync(True#1) Data from Socket#7588182::FinishOperation(SendAsync) 00000000 : 41 42 43 0D 0A Socket#7588182::ReceiveAsync() Exiting Socket#7588182::ReceiveAsync() -> True#1
및 거기 멈춘다. 클라이언트에서 처음 보낸 것처럼 보이지만 서버는 아무런 활동도 보이지 않습니다.
지금은 정보 과부하 일 수 있다고 생각하지만 필요한만큼 자세한 정보를 제공해 드리겠습니다.
감사합니다.