recv chamada () no mesmo soquete o bloqueio de duas threads
Pergunta
O que acontece se eu tiver um socket, s
, não há dados actualmente disponíveis sobre ele, ele é um soquete de bloqueio, e eu chamo recv
sobre ele a partir de dois segmentos de uma vez? Será um dos tópicos obter os dados? Será tanto obtê-lo? Será que a 2ª chamada para retorno recv
com um erro?
Solução
Um segmento vai buscá-la, e não há nenhuma maneira de saber qual.
Este não parece ser um projeto razoável. Existe uma razão pela qual você precisa de duas threads chamando recv()
sobre o mesmo soquete?
Outras dicas
implementações de soquete deve ser thread-safe, então exatamente um segmento deve obter os dados quando ele estiver disponível. A outra chamada deve apenas bloquear.
Não consigo encontrar uma referência para isso, mas aqui está o meu entendimento:
garantia de um fornecedor de thread-segurança pode significar apenas que múltiplos threads cada um pode usar com segurança seus próprios soquetes; Ele não garante atomicity através de uma única chamada, e não promete qualquer atribuição específica de dados do soquete entre vários segmentos.
Suponha que o segmento A chamadas recv () em um soquete que está recebendo dados TCP em streaming a uma taxa elevada. Se recv () precisa ser uma chamada atômica, enrosque A poderia bloquear todos os outros tópicos de executar, porque ele precisa ser executado continuamente para puxar todos os dados (até o buffer está cheio, de qualquer maneira.) Isso não seria Boa. Por isso, eu não diria que recv () é imune a troca de contexto.
Por outro lado, linha Suponha que um faz uma bloqueando chamada para recv () em um soquete TCP, e os dados estão vindo lentamente. Daí a chamada para recv () retorna com errno conjunto para EAGAIN.
Em qualquer destes casos, suponha segmento B chama recv () no mesmo soquete enquanto thread A ainda está recebendo dados. Quando o fio de uma paragem de obtenção de dados entregues a ele para que segmento B pode começar a receber dados? Eu não sei de uma implementação de Unix que vai tentar lembrar que thread A estava no meio de uma operação no soquete; em vez disso, cabe a aplicação (tópicos A e B) para negociar o uso do mesmo.
Geralmente, é melhor para projetar o aplicativo para que apenas um dos tópicos chamará recv () em uma única tomada.
A partir da homem página em recv
A recv () em um SOCK_STREAM tomada retorna como muita informação disponível medida que o tamanho do tampão fornecido lata espera.
Vamos supor que você está usando TCP, uma vez que não foi especificado na pergunta. Então, suponha que você tenha thread A e linha B ambos bloqueio em recv () para o soquete s. Uma vez que s tem alguns dados a serem recebidos ele vai desbloquear um dos tópicos, digamos A, e retornar os dados. Os dados retornados será de alguma tamanho aleatória, tanto quanto estamos preocupados. Tópico A inspeciona os dados recebidos e decide se ele tem uma "mensagem" completa, onde uma mensagem é um conceito de nível de aplicativo.
Thread A decide que não tem uma mensagem completa, por isso chama recv () novamente. Mas, entretanto B já estava bloqueando no mesmo soquete, e recebeu o resto da "mensagem" que foi destinado para a linha A. Eu estou usando destina vagamente aqui.
Agora, tanto segmento A e linha B tem uma mensagem incompleta, e, dependendo de como o código é escrito, jogue os dados afastado como inválido, ou causa erros estranhos e sutis.
Eu gostaria de poder dizer que eu não sei disso por experiência.
Assim, enquanto recv () em si é tecnicamente o segmento de seguros, é uma má idéia ter dois threads chamando-o simultaneamente se você estiver usando-o para TCP.
Tanto quanto eu sei que é completamente seguro quando você estiver usando UDP.
Espero que isso ajude.