eutilizar soquete assíncrono: tentativas subsequentes de conexão falh
Estou tentando reutilizar um soquete em um cliente HTTP assíncrono, mas não consigo conectar ao host pela segunda vez. Basicamente, trato meu cliente HTTP assíncrono como uma máquina de estado com os seguintes estados:
Disponível: o soquete está disponível para usoConnecting: o soquete está se conectando ao endpoint Enviando: o soquete está enviando dados para o endpointReceiving: o soquete está recebendo dados do endpoint Falha: houve uma falha no soqueteLimpar: limpar o estado do soquete No estado de conexão eu chamoBeginConnect
:
private void BeginConnect()
{
lock (_sync) // re-entrant lock
{
IPAddress[] addersses = Dns.GetHostEntry(_asyncTask.Host).AddressList;
// Connect to any available address
IAsyncResult result = _reusableSocket.BeginConnect(addersses, _asyncTask.Port, new AsyncCallback(ConnectCallback), null);
}
}
O método de retorno de chamada altera o estado paraSending
assim que uma conexão bem-sucedida for estabelecida:
private void ConnectCallback(IAsyncResult result)
{
lock (_sync) // re-entrant lock
{
try
{
_reusableSocket.EndConnect(result);
ChangeState(EClientState.Sending);
}
catch (SocketException e)
{
Console.WriteLine("Can't connect to: " + _asyncTask.Host);
Console.WriteLine("SocketException: {0} Error Code: {1}", e.Message, e.NativeErrorCode);
ThreadPool.QueueUserWorkItem(o =>
{
// An attempt was made to get the page so perform a callback
ChangeState(EClientState.Failed);
});
}
}
}
Na limpeza euShutdown
o soquete eDisconnect
com uma bandeira de reutilização:
private void CleanUp()
{
lock (_sync) // re-entrant lock
{
// Perform cleanup
if (_reusableSocket.Connected)
{
_reusableSocket.Shutdown(SocketShutdown.Both);
_reusableSocket.Disconnect(true);
}
ChangeState(EClientState.Available);
}
}
Chamadas subsequentes paraBeginConnect
resulta em um tempo limite e uma exceção:
SocketException: uma tentativa de conexão falhou porque a parte conectada não respondeu adequadamente após um período de tempo ou a conexão estabelecida falhou porque o host conectado falhou ao responder XX.XXX.XX.XX: 80
Código de erro: 10060
Aqui está o rastreio de estado:
Initializing...
Change State: Connecting
Change State: Sending
Change State: Receiving
Change State: CleanUp
Callback: Received data from client 0 // <--- Received the first data
Change State: Available
Change State: Connecting // <--- Timeout when I try to reuse the socket to connect to a different endpoint
O que devo fazer para reutilizar o soquete para conectar-me a um host diferente?
Nota: eu tenhonã tentou se reconectar ao mesmo host, masEu assum acontece o mesmo (ou seja, falha na conexão).
Atualiza
Encontrei a seguinte nota no documentação do BeginConnect:
Se esse soquete tiver sido desconectado anteriormente, o BeginConnect deverá ser chamado em um encadeamento que não sairá até que a operação seja concluída. Essa é uma limitação do provedor subjacente. Além disso, o EndPoint usado deve ser diferent
Estou começando a me perguntar se meu problema tem algo a ver com isso ... Estou me conectando a um EndPoint diferente, mas o que eles significam que o encadeamento do qual chamamos BeginConnect não deve sair até que a operação seja concluída?
Update 2.0:
Eu perguntei a questão relacionada e tentei usar as chamadas "família assíncrona" em vez das chamadas "família iniciada", mas tenho o mesmo problema !!!