====== 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;
}