{"id":21442250,"url":"https://github.com/thotypous/redes-p2","last_synced_at":"2026-01-23T00:28:31.817Z","repository":{"id":69726849,"uuid":"400512086","full_name":"thotypous/redes-p2","owner":"thotypous","description":null,"archived":false,"fork":false,"pushed_at":"2025-09-04T03:11:52.000Z","size":28,"stargazers_count":2,"open_issues_count":0,"forks_count":3,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-09-04T05:32:05.142Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/thotypous.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-08-27T13:06:36.000Z","updated_at":"2025-09-04T03:12:20.000Z","dependencies_parsed_at":"2023-03-12T23:15:47.075Z","dependency_job_id":null,"html_url":"https://github.com/thotypous/redes-p2","commit_stats":null,"previous_names":[],"tags_count":0,"template":true,"template_full_name":null,"purl":"pkg:github/thotypous/redes-p2","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thotypous%2Fredes-p2","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thotypous%2Fredes-p2/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thotypous%2Fredes-p2/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thotypous%2Fredes-p2/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/thotypous","download_url":"https://codeload.github.com/thotypous/redes-p2/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thotypous%2Fredes-p2/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28676145,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-22T20:48:19.482Z","status":"ssl_error","status_checked_at":"2026-01-22T20:48:14.968Z","response_time":144,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-23T01:53:12.894Z","updated_at":"2026-01-23T00:28:31.805Z","avatar_url":"https://github.com/thotypous.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Camada de transporte (L4) – TCP\n\nNesta prática, vamos implementar um protótipo de um protocolo compatível com o TCP. Focaremos na ponta do servidor. Este roteiro te guiará em passos para que você construa aos poucos uma implementação completa.\n\nAo longo de anos oferecendo essa disciplina, eu observo que os estudantes sempre preferem entregar o T1 em Python, então vamos assumir que vocês vão continuar usando a mesma linguagem. Caso decida usar outra linguagem, você terá de adaptar também os testes.\n\nSua implementação deve ser realizada no arquivo `tcp.py`, que já veio com um esqueleto em cima do qual você vai construir o seu código. Para ajudar na sua implementação, você pode chamar as funções e usar os valores que já vieram declarados no arquivo [tcputils.py](tcputils.py). Pode ser útil, também, consultar a [página sobre o formato do segmento TCP na Wikipedia](https://en.wikipedia.org/wiki/Transmission_Control_Protocol#TCP_segment_structure). Os [slides do livro-texto](https://1drv.ms/f/s!AlU8gesWGe8VeyYUZqcZmeP52vY) relevantes para esta prática são os do Capítulo 3.\n\nImplemente o seu TCP no arquivo [tcp.py](tcp.py). **NÃO MODIFIQUE O CONTEÚDO DOS OUTROS ARQUIVOS**.\n\n## Testes automatizados\n\nPara testar seu código localmente, use o runner de testes padrão do Python (`unittest`). Os testes estão no pacote `tests` e foram escritos para serem descobertos e executados com o comando abaixo:\n\n```sh\npython3 -m unittest\n```\n\nPara executar um teste específico (por exemplo, o que verifica a implementação do Passo 1):\n\n```sh\npython3 -m unittest tests.test1\n```\n\n## Passo 1 — 1 ponto\n\nImplemente o código necessário para aceitar uma conexão. O código base já veio com um `if` para verificar se chegou um segmento com a *flag* `SYN`. Como vimos no slide 80 do livro, isso significa que um cliente está querendo abrir uma nova conexão. Você deve responder ao `SYN` com um `SYN+ACK` para aceitar a conexão.\n\nOs locais sugeridos para preencher seu código são no método `_rdt_rcv` da classe `Servidor`, ou então no construtor da classe `Conexao`.\n\nLembre-se que, como resposta, o cliente vai enviar um segmento contendo a *flag* `ACK` que, além disso, também já pode conter os primeiros dados enviados pelo cliente. Mas disso nós vamos tratar no próximo passo.\n\n## Passo 2 — 1 ponto\n\nO recebimento de segmentos no TCP é similar ao GBN, descrito no slide 49 do livro. Ao tratar um segmento proveniente da camada de rede, assegure-se que ele não é duplicado e que foi recebido em ordem antes de repassá-lo para a camada de aplicação.\n\nPor simplicidade, confirme cada segmento que for recebido corretamente mandando um segmento com a *flag* `ACK` e com *payload* vazio.\n\nPreencha o método `_rdt_rcv` da classe `Conexao` para implementar essa funcionalidade.\n\n## Passo 3 — 1 ponto\n\nO funcionamento básico do envio de segmentos pelo TCP é descrito no slide 67 do livro. Vamos quebrar a implementação em duas partes.\n\nNesta primeira parte, vamos nos preocupar somente com o evento \"dados recebidos da camada de aplicação acima\". Ou seja, mantenha uma contagem correta do número de sequência a ser inserido no segmento e construa o segmento corretamente, enviando-o em seguida para a camada de rede.\n\nPreencha o método `enviar` da classe `Conexao` para implementar essa funcionalidade.\n\nPor simplicidade, mantenha a *flag* de `ACK` sempre ligada nos segmentos que você enviar, incluindo corretamente o *acknowledgement number* correspondente ao próximo byte que você espera receber. Note que essa contagem refere-se ao funcionamento da nossa ponta como *receptor*, e não como *transmissor*, mas aqui misturamos os papéis.\n\n## Passo 4 — 1 ponto\n\nAntes de prosseguirmos com a segunda parte da implementação da máquina de estados de envio, sugerimos dar uma pausa e tratar antes do fechamento de conexões. Assim, você terá um protótipo básico que poderá ser usado para conversar, por exemplo, com o `nc`, desde que você esteja em uma rede ideal (sem perdas, com banda sobrando, etc.)\n\nO fechamento de conexões é descrito no slide 83 do livro. Uma das pontas escolhe fechar a conexão, enviando um segmento com *flag* `FIN`. A outra ponta confirma o recebimento do `FIN` mandando um `ACK`. Para que o encerramento da conexão ocorra de forma limpa, a outra ponta deve eventualmente fazer a mesma coisa (fechar a conexão enviando um `FIN`).\n\nPor simplicidade, você pode assumir que o cliente é o primeiro a pedir para fechar a conexão.\n\nQuando receber o pedido de fechamento, faça o *callback* da classe *Conexao* ser chamado passando como o argumento `dados` uma string de bytes vazia (`b''`), para sinalizar o fechamento da conexão para a camada de aplicação, além de responder corretamente com um `ACK`.\n\nQuando o método `fechar` da classe *Conexao* for chamado, envie um segmento com *flag* `FIN`.\n\nSe você implementou todos os passos até aqui, você deve ser capaz de executar o arquivo `./exemplo_integracao.py` em um sistema Linux (leia antes os comentários no início do arquivo) e testá-lo conectando-se a ele com o comando `nc localhost 7000`.\n\n## Passo 5 — 2 pontos\n\nVamos, agora, voltar ao slide 67 do livro para implementar a segunda parte do transmissor. Faça a sua implementação ser capaz de lidar com perda de pacotes. Para isso, você vai precisar de um *timer*. Há um exemplo no código, mas ele está posicionado no local errado: você deve movê-lo para os locais do código onde realmente é necessário iniciar um *timer*. Por enquanto, você pode usar um valor constante (não use um valor muito grande!) para o intervalo do *timer*.\n\nAlém disso, você precisará tratar os `ACK`s que chegarem pelo método `_rdt_rcv` da classe `Conexao`.\n\n## Passo 6 — 2 pontos\n\nCalcule o `TimeoutInterval` de acordo com as equações dos slides 62 e 63 e passe a usar esse valor como intervalo dos *timers* que você criar.\n\nPara medir o `SampleRTT`, meça o tempo que se passa (por exemplo, com `time.time()`) entre você enviar um segmento e receber o `ACK` dele. Não leve em conta segmentos que estiverem sendo retransmitidos, apenas aqueles que estiverem sendo transmitidos pela primeira vez.\n\nQuando você medir o primeiro `SampleRTT` de uma conexão, em vez de usar as equações, inicialize os valores atribuindo `EstimatedRTT` e `DevRTT` com `SampleRTT` e `SampleRTT/2`, respectivamente, como sugerido pela RFC 2988.\n\n## Passo 7 — 2 pontos\n\nImplemente um mecanismo de controle de congestionamento simplificado similar ao AIMD (descrito no slide 96 do livro). Quando uma conexão for aberta, comece com uma janela de 1 MSS. Sempre que você receber `ACK` de uma janela inteira, aumente a janela de mais 1 MSS. Se ocorrer um *timeout* no *timer*, reduza a janela pela metade.\n\n## Adiante a prática final!\n\nO arquivo `exemplo_integracao.py` vem com um exemplo de camada de aplicação que faz eco, ou seja, envia de volta para o cliente tudo que receber dele.\n\nSe você tiver feito a Prática 1, experimente adaptá-la para usar o TCP que você escreveu agora na Prática 2 (de acordo com o `exemplo_integracao.py`) e depois executar `./servidor`. Talvez você pegue erros de implementação que não tenham sido detectados pelos testes! Se isso acontecer, entre em contato com o professor para que possamos melhorar os testes para edições futuras da disciplina.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthotypous%2Fredes-p2","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthotypous%2Fredes-p2","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthotypous%2Fredes-p2/lists"}