Construa os programas mínimos que trocam texto por um socket TCP — lado servidor e lado cliente.
socket() — cria socketbind() — associa a uma portalisten() — começa a escutaraccept() — aceita uma conexãorecv() / send()close()socket() — cria socketconnect() — alcança o servidorsend() / recv()close()bind/listen/accept são exclusivos do servidor; connect é exclusivo do cliente. Todo o resto é compartilhado.#include <stdio.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/socket.h> #define PORT 12345 #define BUF_SIZE 1024 int main(void) { // 1. cria o socket int listen_fd = socket(AF_INET, SOCK_STREAM, 0); if (listen_fd < 0) { perror("socket"); return 1; } // (recomendado) permite reutilizar a porta rapidamente int yes = 1; setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)); // 2. prepara o endereço em que vai escutar struct sockaddr_in addr; memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl(INADDR_ANY); // qualquer IP local addr.sin_port = htons(PORT); // 3. bind — associa o socket à porta if (bind(listen_fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) { perror("bind"); return 1; } // 4. listen — começa a aceitar conexões if (listen(listen_fd, 1) < 0) { perror("listen"); return 1; } printf("Escutando na porta %d...\n", PORT); // 5. aceita um cliente struct sockaddr_in client_addr; socklen_t clen = sizeof(client_addr); int conn_fd = accept(listen_fd, (struct sockaddr*)&client_addr, &clen); if (conn_fd < 0) { perror("accept"); return 1; } printf("Cliente conectado: %s\n", inet_ntoa(client_addr.sin_addr)); // 6. laço de eco — lê o que chega e envia de volta char buf[BUF_SIZE]; ssize_t n; while ((n = recv(conn_fd, buf, BUF_SIZE - 1, 0)) > 0) { buf[n] = '\0'; printf("recebido: %s", buf); send(conn_fd, buf, n, 0); // envia os mesmos bytes de volta } // 7. limpeza close(conn_fd); close(listen_fd); printf("Conexão fechada\n"); return 0; }
inet_addr("127.0.0.1").#include <stdio.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/socket.h> #define PORT 12345 #define BUF_SIZE 1024 int main(void) { // 1. cria o socket int sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) { perror("socket"); return 1; } // 2. endereço alvo: localhost:12345 struct sockaddr_in addr; memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(PORT); addr.sin_addr.s_addr = inet_addr("127.0.0.1"); // 3. connect — alcança o servidor if (connect(sockfd, (struct sockaddr*)&addr, sizeof(addr)) < 0) { perror("connect"); return 1; } printf("Conectado. Digite uma mensagem e Enter:\n"); // 4. lê uma linha do stdin e envia char msg[BUF_SIZE]; if (fgets(msg, BUF_SIZE, stdin) == NULL) return 1; send(sockfd, msg, strlen(msg), 0); // 5. recebe a resposta char buf[BUF_SIZE]; ssize_t n = recv(sockfd, buf, BUF_SIZE - 1, 0); if (n > 0) { buf[n] = '\0'; printf("Servidor respondeu: %s", buf); } // 6. fecha close(sockfd); return 0; }
127.0.0.1 (localhost), então rode o servidor na mesma máquina. Para alcançar uma máquina diferente, use o IP dela.bind: Address already in use — outro processo ainda segura a porta. Espere um pouco ou escolha outra porta.connect: Connection refused — o servidor não está rodando, ou a porta/IP está errado.accept.toupper de <ctype.h>.accept, chame fork() para cada cliente ser atendido por um processo filho enquanto o pai volta ao accept../echo_server 8080. Leia de argv[1]. Veja a aula de argc/argv.Teste seu entendimento desta aula!
bind associa o socket a um endereço/porta, listen o coloca em modo de escuta e accept completa uma conexão entrante.
Depois de criar um socket, o cliente chama connect para alcançar o servidor. bind e accept são chamadas do lado servidor.
Para IPv4 é sockaddr_in. IPv6 usa sockaddr_in6, e sockaddr é o tipo genérico.