====== Klient TCP odbierz - wyślij ====== #include #include #include #include #include #include #include #include #include #include ssize_t readData(int fd, char * buffer, ssize_t buffsize){ auto ret = read(fd, buffer, buffsize); if(ret==-1) error(1,errno, "read failed on descriptor %d", fd); return ret; } void writeData(int fd, char * buffer, ssize_t count){ auto ret = write(fd, buffer, count); if(ret==-1) error(1, errno, "write failed on descriptor %d", fd); if(ret!=count) error(0, errno, "wrote less than requested to descriptor %d (%ld/%ld)", fd, count, ret); } int main(int argc, char ** argv){ if(argc!=3) error(1,0,"Need 2 args"); // Resolve arguments to IPv4 address with a port number addrinfo *resolved, hints={.ai_flags=0, .ai_family=AF_INET, .ai_socktype=SOCK_STREAM}; int res = getaddrinfo(argv[1], argv[2], &hints, &resolved); if(res || !resolved) error(1, errno, "getaddrinfo"); // create socket int sock = socket(resolved->ai_family, resolved->ai_socktype, 0); if(sock == -1) error(1, errno, "socket failed"); // attept to connect res = connect(sock, resolved->ai_addr, resolved->ai_addrlen); if(res) error(1, errno, "connect failed"); // free memory freeaddrinfo(resolved); /****************************/ // read from socket, write to stdout ssize_t bufsize1 = 255, received1; char buffer1[bufsize1]; received1 = readData(sock, buffer1, bufsize1); writeData(1, buffer1, received1); /****************************/ // read from stdin, write to socket ssize_t bufsize2 = 255, received2; char buffer2[bufsize2]; received2 = readData(0, buffer2, bufsize2); writeData(sock, buffer2, received2); /****************************/ close(sock); return 0; } ====== Serwer TCP połącz - wyślij do wszystkich ====== #include #include #include #include #include #include #include #include #include #include #include #include #include #include // server socket int servFd; // client sockets std::unordered_set clientFds; // handles SIGINT void ctrl_c(int); // sends data to clientFds excluding fd void sendToAllBut(int fd, char * buffer, int count); // converts cstring to port uint16_t readPort(char * txt); // sets SO_REUSEADDR void setReuseAddr(int sock); int main(int argc, char ** argv){ // get and validate port number if(argc != 2) error(1, 0, "Need 1 arg (port)"); auto port = readPort(argv[1]); // create socket servFd = socket(AF_INET, SOCK_STREAM, 0); if(servFd == -1) error(1, errno, "socket failed"); // graceful ctrl+c exit signal(SIGINT, ctrl_c); // prevent dead sockets from throwing pipe errors on write signal(SIGPIPE, SIG_IGN); setReuseAddr(servFd); // bind to any address and port provided in arguments sockaddr_in serverAddr{.sin_family=AF_INET, .sin_port=htons((short)port), .sin_addr={INADDR_ANY}}; int res = bind(servFd, (sockaddr*) &serverAddr, sizeof(serverAddr)); if(res) error(1, errno, "bind failed"); // enter listening mode res = listen(servFd, 1); if(res) error(1, errno, "listen failed"); /****************************/ while(true){ // prepare placeholders for client address sockaddr_in clientAddr{0}; socklen_t clientAddrSize = sizeof(clientAddr); // accept new connection auto clientFd = accept(servFd, (sockaddr*) &clientAddr, &clientAddrSize); if(clientFd == -1) error(1, errno, "accept failed"); // add client to all clients set clientFds.insert(clientFd); // tell who has connected printf("new connection from: %s:%hu (fd: %d)\n", inet_ntoa(clientAddr.sin_addr), ntohs(clientAddr.sin_port), clientFd); /****************************/ // read a message char buffer[255]; int count = read(clientFd, buffer, 255); if(count < 1) { printf("removing %d\n", clientFd); clientFds.erase(clientFd); close(clientFd); continue; } else { // broadcast the message sendToAllBut(clientFd, buffer, count); } } /****************************/ } uint16_t readPort(char * txt){ char * ptr; auto port = strtol(txt, &ptr, 10); if(*ptr!=0 || port<1 || (port>((1<<16)-1))) error(1,0,"illegal argument %s", txt); return port; } void setReuseAddr(int sock){ const int one = 1; int res = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); if(res) error(1,errno, "setsockopt failed"); } void ctrl_c(int){ for(int clientFd : clientFds) close(clientFd); close(servFd); printf("Closing server\n"); exit(0); } void sendToAllBut(int fd, char * buffer, int count){ int res; decltype(clientFds) bad; for(int clientFd : clientFds){ if(clientFd == fd) continue; res = write(clientFd, buffer, count); if(res!=count) bad.insert(clientFd); } for(int clientFd : bad){ printf("removing %d\n", clientFd); clientFds.erase(clientFd); close(clientFd); } } ====== Nawiązanie połączenia TCP ====== #include #include #include #include #include #include int main(int argc, char ** argv){ if(argc!=3) error(1,0,"Need 2 args"); addrinfo *ao; int res = getaddrinfo(argv[1],argv[2],nullptr, &ao); if(res || !ao) error(1,errno, "getaddrinfo"); int sock = socket(ao->ai_family, SOCK_STREAM, 0); if(sock<0) error(1,errno, "socket"); res = connect(sock, ao->ai_addr, ao->ai_addrlen); if(res) error(1,errno, "connect"); freeaddrinfo(ao); // ... return 0; }