사용자 지정 TCP/IP 클라이언트/서버 응용 프로그램을 만드는 중이며 서버를 중지하려고 할 때 방해가됩니다. 원래, 내 코드는 지정된 포트에서 수신 한 TcpListener를 사용하고, 내 (편의를 위해 간체) 코드는 시작하고 다음과 같이 서버가 갔다 중지 :TCP 수신기가 닫힌 경우 감지 문제
private bool state;
private TcpListener listener;
private CancellationTokenSource tokenSource;
private Dictionary<string, ConnectedClient> clients;
private List<Task> clientTasks;
private ConnectedClient command_client;
public async Task RunServer() {
if (!state) {
state = true;
tokenSource = new CancellationTokenSource();
listener = new TcpListener(IPAddress.Any, 55001);
listener.Start();
while (true) {
try {
TcpClient socketClient = await listener.AcceptTcpClientAsync();
ConnectedClient client = new ConnectedClient(socketClient);
clients.Add(client.id, client);
client.task = ProcessClientAsync(client, tokenSource.Token);
clientTasks.Add(client.task);
}
catch (ObjectDisposedException) {
//Server stopped by user
//exit while
break;
}
}
/* Server has been stopped; close all connections */
CloseAll();
}
else {
/* Stop the server */
tokenSource.Cancel();
listener.Stop();
/* Clean up of currently connected clients is handled in CloseAll, handled upon ObjectDisposedException above */
}
}
ConnectedClient 내가에 대한 몇 가지 정보를 개최 쓴 클래스입니다 개별 클라이언트를 편리하게 사용할 수 있으며 데이터 수신시 발생하는 상황을 처리하는 기능을 제공합니다. 간결하게하기 위해 몇 가지 사항을 남겨 두었습니다.하지만이 코드는 내가 원하는 것을 정확히 수행합니다. 서버는 연결을 기다리고, 수신 된 연결을 처리하기 위해 ConnectedClient 객체를 생성하고, 대기 상태로 돌아갑니다. 서버가 이미 청취 중일 때이 함수가 호출되면 리스너가 중지되어 리스너가 예외를 throw하여 루프를 중단하고 모든 연결을 닫습니다.
두 개의 서로 다른 포트에서 수신 대기하는 서버를 만들려고 시도 할 때 발생합니다. 다르게 처리해야하는 포트입니다. 여기
은 (는 시도)에 대한 내 코드 즉 :private bool state;
private Dictionary<string, ConnectedClient> clients;
private TcpListener command_listener;
private TcpListener query_listener;
private CancellationTokenSource tokenSource;
private List<Task> clientTasks;
public async Task RunServer() {
if (!state) {
state = true;
tokenSource = new CancellationTokenSource();
command_listener = new TcpListener(IPAddress.Any, 55001);
command_listener.Start();
query_listener = new TcpListener(IPAddress.Any, 55002);
query_listener.Start();
Task prevCommand = null;
Task prevQuery = null;
while (true) {
try {
if (prevCommand == null || prevCommand.IsCompleted) {
prevCommand = waitForConnections(command_listener);
}
if (prevQuery == null || prevQuery.IsCompleted) {
prevQuery = waitForConnections(query_listener);
}
await Task.WhenAny(prevCommand, prevQuery);
}
catch (ObjectDisposedException) {
//Server stopped by user
//exit while
break;
}
}
/* Server has been stopped; close all connections */
CloseAll();
}
else {
/* Stop the server */
tokenSource.Cancel();
command_listener.Stop();
query_listener.Stop();
/* Clean up of currently connected clients is handled in CloseAll, handled upon ObjectDisposedException above */
}
}
waitForConnections의 목적은 하나 개의 포트에 연결을 기다리는 것은 또한 다른 한편으로 연결을 차단하지 않도록 연결 요청을 처리하는 것입니다 하나의 연결 만이 함께 포트 55001.
public async Task waitForConnections(TcpListener listener) {
TcpClient socketClient = await listener.AcceptTcpClientAsync();
if (((IPEndPoint)listener.LocalEndpoint).Port == 55001) {
if (command_client == null) {
command_client = new ConnectedClient(socketClient, onClientUpdate, onResend);
clients.Add(command_client.id, command_client);
command_client.task = ProcessClientAsync(command_client, tokenSource.Token);
clientTasks.Add(command_client.task);
}
else {
//only one client allowed on this port, reject the connection
socketClient.Close();
}
}
else {
ConnectedClient client = new ConnectedClient(socketClient, onClientUpdate, onResend);
clients.Add(client.id, client);
client.task = ProcessClientAsync(client, tokenSource.Token);
clientTasks.Add(client.task);
}
}
에 할 수 있도록, 나는 차단, 그러나 다시이 함수를 호출하고 리스너를 중지하는 원인이하지 않는 것없이 두 개의 포트에 클라이언트를 연결할 수 있어요 ObjectDisposedException를 사용하여 예상대로 던져져서 전체 프로그램이 멈추고 아무것도하지 않게됩니다. 이것은 비동기 함수의 무책임한 사용으로 인한 것 같지만 어떻게 해결할 수 있습니까?
ObjectDisposedExceptions을 강제 종료하여 어떤 형태의 연결 종료를 나타내는 의도 된 접근 방식이 완전히 잘못되었습니다. 어쨌든, TcpListener 객체를 멈추더라도 그 객체는 처리되지 않습니다. – elgonzo
공정하게, 예외 상황을 추적하는 것은 내가 생각하기에 나쁜 습관입니다. 그리고 처분이 끝날 때까지 나는 그 질문과 관련이 있다고 생각하지 않았기 때문에 간결하게 그 것을 버렸다. 내 진짜 질문은, 왜, 예외는 첫 번째 경우에는 던져 지겠지만, 두 번째에는 던지지 않는 이유일까요? – Cobalt
죄송합니다, 다시 나는 명확하지 않았습니다. 왜 내 마음을 읽을 수 없니? ;) 첫 번째 경우에는 TcpListener.Stop() 호출만으로 ObjectDisposedException을 던졌지만 두 번째 경우에는 그렇지 않습니다. 청취자를 중지시키지 않아도 청취자가 그것을 처분하지 않는다면, 왜 그것이 처음부터 효과가 있었 을까? – Cobalt