diff --git a/.gitignore b/.gitignore index acf5dd9..a97981c 100644 --- a/.gitignore +++ b/.gitignore @@ -86,3 +86,4 @@ dkms.conf *.out *.app +**/build \ No newline at end of file diff --git a/intro/Makefile b/intro/Makefile new file mode 100644 index 0000000..aa6a065 --- /dev/null +++ b/intro/Makefile @@ -0,0 +1,10 @@ +srcfiles = $(wildcard *.c) +CC = gcc +CFLAGS += -Wall -lunp +objs = $(basename $(srcfiles)) + +all: + @for obj in $(objs); do \ + $(CC) $$obj.c $(CFLAGS) -o build/$$obj; \ + done +.PHONY: all \ No newline at end of file diff --git a/intro/byteorder.c b/intro/byteorder.c new file mode 100644 index 0000000..1c9864c --- /dev/null +++ b/intro/byteorder.c @@ -0,0 +1,24 @@ +#include "unp.h" + +int main(int argc, char* argv[]) +{ + union + { + short s; + char c[sizeof(short)]; + } un; + un.s = 0x0102; + printf("%s: ", CPU_VENDOR_OS); + size_t size_of_short = sizeof(short); + if(size_of_short == 2) { + if(un.c[0] == 1 && un.c[1] == 2) + printf("big-endian\n"); + else if(un.c[0] == 2 && un.c[1] == 1) + printf("little-endian\n"); + else + printf("unknown\n"); + + } else { + printf("sizeof(short) = %ld\n", size_of_short); + } +} \ No newline at end of file diff --git a/intro/daytimetcpcli.c b/intro/daytimetcpcli.c new file mode 100644 index 0000000..498eb4c --- /dev/null +++ b/intro/daytimetcpcli.c @@ -0,0 +1,33 @@ +#include "unp.h" + +int main(int argc, char ** argv) +{ + int sockfd, n; + char recvline[MAXLINE + 1]; + struct sockaddr_in servaddr; + + if(argc != 2) + err_quit("usage: a.out "); + + if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) + err_sys("socket error"); + + bzero(&servaddr, sizeof(servaddr)); + servaddr.sin_family = AF_INET; + servaddr.sin_port = htons(10013); // daytime server + if(inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0) + err_quit("inet_pton error for %s", argv[1]); + + if(connect(sockfd, (SA *)&servaddr, sizeof(servaddr)) < 0) + err_sys("connect error"); + + while((n = read(sockfd, recvline, MAXLINE)) > 0) { + recvline[n] = 0; // null terminate + if(fputs(recvline, stdout) == EOF) + err_sys("fputs error"); + } + if(n < 0) + err_sys("read error"); + exit(0); + +} \ No newline at end of file diff --git a/intro/daytimetcpcliv6.c b/intro/daytimetcpcliv6.c new file mode 100644 index 0000000..a18d943 --- /dev/null +++ b/intro/daytimetcpcliv6.c @@ -0,0 +1,33 @@ +#include "unp.h" + +int main(int argc, char ** argv) +{ + int sockfd, n; + char recvline[MAXLINE + 1]; + struct sockaddr_in6 servaddr; + + if(argc != 2) + err_quit("usage: a.out "); + + if((sockfd = socket(AF_INET6, SOCK_STREAM, 0)) < 0) + err_sys("socket error"); + + bzero(&servaddr, sizeof(servaddr)); + servaddr.sin6_family = AF_INET6; + servaddr.sin6_port = htons(13); // daytime server + if(inet_pton(AF_INET6, argv[1], &servaddr.sin6_addr) <= 0) + err_quit("inet_pton error for %s", argv[1]); + + if(connect(sockfd, (SA *)&servaddr, sizeof(servaddr)) < 0) + err_sys("connect error"); + + while((n = read(sockfd, recvline, MAXLINE)) > 0) { + recvline[n] = 0; // null terminate + if(fputs(recvline, stdout) == EOF) + err_sys("fputs error"); + } + if(n < 0) + err_sys("read error"); + exit(0); + +} \ No newline at end of file diff --git a/intro/daytimetcpsrv.c b/intro/daytimetcpsrv.c new file mode 100644 index 0000000..965f971 --- /dev/null +++ b/intro/daytimetcpsrv.c @@ -0,0 +1,28 @@ +#include "unp.h" +#include + +int main(int argc, char *argv[]) +{ + int listenfd, connfd; + struct sockaddr_in servaddr; + char buff[MAXLINE]; + time_t ticks; + + listenfd = Socket(AF_INET, SOCK_STREAM, 0); + + bzero(&servaddr, sizeof(servaddr)); + servaddr.sin_family = AF_INET; + servaddr.sin_addr.s_addr = htonl(INADDR_ANY); + servaddr.sin_port = htons(10013); // daytime server + + Bind(listenfd, (SA *)&servaddr, sizeof(servaddr)); + Listen(listenfd, LISTENQ); + for(;;) { + connfd = Accept(listenfd, (SA *) NULL, NULL); + ticks = time(NULL); + snprintf(buff, sizeof(buff), "Hello, Stupid Bitch ! %.24s\r\n", ctime(&ticks)); + Write(connfd, buff, strlen(buff)); + Close(connfd); + } + +} diff --git a/intro/daytimetcpsrv1.c b/intro/daytimetcpsrv1.c new file mode 100644 index 0000000..b818c46 --- /dev/null +++ b/intro/daytimetcpsrv1.c @@ -0,0 +1,32 @@ +#include "unp.h" +#include + +int main(int argc, char *argv[]) +{ + int listenfd, connfd; + struct sockaddr_in servaddr, cliaddr; + socklen_t len; + char buff[MAXLINE]; + time_t ticks; + + listenfd = Socket(AF_INET, SOCK_STREAM, 0); + + bzero(&servaddr, sizeof(servaddr)); + servaddr.sin_family = AF_INET; + servaddr.sin_addr.s_addr = htonl(INADDR_ANY); + servaddr.sin_port = htons(10013); // daytime server + + Bind(listenfd, (SA *)&servaddr, sizeof(servaddr)); + Listen(listenfd, LISTENQ); + for(;;) { + len = sizeof(cliaddr); + connfd = Accept(listenfd, (SA *) &cliaddr, &len); + printf("connection from %s, port %d\n", + Inet_ntop(AF_INET, &cliaddr.sin_addr, buff, sizeof(buff)), ntohs(cliaddr.sin_port)); + ticks = time(NULL); + snprintf(buff, sizeof(buff), "Hello, Stupid Bitch ! %.24s\r\n", ctime(&ticks)); + Write(connfd, buff, strlen(buff)); + Close(connfd); + } + +} diff --git a/intro/daytimetcpsrv2.c b/intro/daytimetcpsrv2.c new file mode 100644 index 0000000..65ec830 --- /dev/null +++ b/intro/daytimetcpsrv2.c @@ -0,0 +1,40 @@ +#include "unp.h" +#include + +int main(int argc, char *argv[]) +{ + int listenfd, connfd; + struct sockaddr_in servaddr, cliaddr; + socklen_t len; + char buff[MAXLINE]; + time_t ticks; + pid_t pid; + + listenfd = Socket(AF_INET, SOCK_STREAM, 0); + + bzero(&servaddr, sizeof(servaddr)); + servaddr.sin_family = AF_INET; + servaddr.sin_addr.s_addr = htonl(INADDR_ANY); + servaddr.sin_port = htons(10013); // daytime server + + Bind(listenfd, (SA *)&servaddr, sizeof(servaddr)); + Listen(listenfd, LISTENQ); + for(;;) { + connfd = Accept(listenfd, (SA *) &cliaddr, &len); + if((pid = fork()) == 0) { + len = sizeof(cliaddr); + Close(listenfd); + printf("connection from %s, port %d, pid %d\n", + Inet_ntop(AF_INET, &cliaddr.sin_addr, buff, sizeof(buff)), ntohs(cliaddr.sin_port), getpid()); + sleep(5); + printf("after 5 seconds\n"); + ticks = time(NULL); + snprintf(buff, sizeof(buff), "Hello, Stupid Bitch ! %.24s\r\n", ctime(&ticks)); + Write(connfd, buff, strlen(buff)); + Close(connfd); + exit(0); + } + Close(connfd); + } + +} diff --git a/select/Makefile b/select/Makefile new file mode 100644 index 0000000..aa6a065 --- /dev/null +++ b/select/Makefile @@ -0,0 +1,10 @@ +srcfiles = $(wildcard *.c) +CC = gcc +CFLAGS += -Wall -lunp +objs = $(basename $(srcfiles)) + +all: + @for obj in $(objs); do \ + $(CC) $$obj.c $(CFLAGS) -o build/$$obj; \ + done +.PHONY: all \ No newline at end of file diff --git a/select/strcliselect01.c b/select/strcliselect01.c new file mode 100644 index 0000000..0a46388 --- /dev/null +++ b/select/strcliselect01.c @@ -0,0 +1,52 @@ +#include "unp.h" + +void str_cli(FILE *, int); + +int main(int argc, char* argv[]) +{ + int sockfd; + struct sockaddr_in servaddr; + + if(argc != 2) + err_quit("usage: tcpcli "); + + sockfd = Socket(AF_INET, SOCK_STREAM, 0); + bzero(&servaddr, sizeof(servaddr)); + servaddr.sin_family = AF_INET; + servaddr.sin_port = htons(SERV_PORT); + Inet_pton(AF_INET, argv[1], &servaddr.sin_addr); + + Connect(sockfd, (SA *) &servaddr, sizeof(servaddr)); + + str_cli(stdin, sockfd); + + exit(0); + +} + +void str_cli(FILE *fp, int sockfd) +{ + int maxfdp1; + fd_set rset; + char sendline[MAXLINE], recvline[MAXLINE]; + + FD_ZERO(&rset); + for(;;) { + FD_SET(fileno(fp), &rset); + FD_SET(sockfd, &rset); + maxfdp1 = max(fileno(fp), sockfd) + 1; + Select(maxfdp1, &rset, NULL, NULL, NULL); + + if(FD_ISSET(sockfd, &rset)) { // socket is readable + if(Readline(sockfd, recvline, MAXLINE) == 0) + err_quit("str_cli: server terminated prematurely"); + Fputs(recvline, stdout); + } + + if(FD_ISSET(fileno(fp), &rset)) { // input is readable + if(Fgets(sendline, MAXLINE, fp) == NULL) + return; // all done + Writen(sockfd, sendline, strlen(sendline)); + } + } +} \ No newline at end of file diff --git a/select/strcliselect02.c b/select/strcliselect02.c new file mode 100644 index 0000000..76a2384 --- /dev/null +++ b/select/strcliselect02.c @@ -0,0 +1,63 @@ +#include "unp.h" + +void str_cli(FILE *, int); + +int main(int argc, char* argv[]) +{ + int sockfd; + struct sockaddr_in servaddr; + + if(argc != 2) + err_quit("usage: tcpcli "); + + sockfd = Socket(AF_INET, SOCK_STREAM, 0); + bzero(&servaddr, sizeof(servaddr)); + servaddr.sin_family = AF_INET; + servaddr.sin_port = htons(SERV_PORT); + Inet_pton(AF_INET, argv[1], &servaddr.sin_addr); + + Connect(sockfd, (SA *) &servaddr, sizeof(servaddr)); + + str_cli(stdin, sockfd); + + exit(0); + +} + +void str_cli(FILE *fp, int sockfd) +{ + int maxfdp1, stdineof; + fd_set rset; + char buf[MAXLINE]; + int n; + + stdineof = 0; + FD_ZERO(&rset); + for(;;) { + if(stdineof == 0) + FD_SET(fileno(fp), &rset); + FD_SET(sockfd, &rset); + maxfdp1 = max(fileno(fp), sockfd) + 1; + Select(maxfdp1, &rset, NULL, NULL, NULL); + + if(FD_ISSET(sockfd, &rset)) { // socket is readable + if((n = Read(sockfd, buf, MAXLINE)) == 0) { + if (stdineof == 1) + return; // normal termination + else + err_quit("str_cli: server terminated prematurely"); + } + Write(fileno(stdout), buf, n); + } + + if(FD_ISSET(fileno(fp), &rset)) { // input is readable + if( (n=Read(fileno(fp), buf, MAXLINE)) == 0) { + stdineof = 1; + Shutdown(sockfd, SHUT_WR); // send FIN + FD_CLR(fileno(fp), &rset); + continue; + } + Writen(sockfd, buf, n); + } + } +} \ No newline at end of file diff --git a/select/tcpsrvpoll01.c b/select/tcpsrvpoll01.c new file mode 100644 index 0000000..8e9225d --- /dev/null +++ b/select/tcpsrvpoll01.c @@ -0,0 +1,88 @@ +#include "unp.h" +#include // for OPEN_MAX + +#ifndef OPEN_MAX +#define OPEN_MAX _SC_OPEN_MAX +#endif + + +int main(int argc, char *argv[]) +{ + int listenfd, confd, sockfd, maxi, i; + int nready; + ssize_t n; + char buf[MAXLINE]; + socklen_t clilen; + struct pollfd client[OPEN_MAX]; + struct sockaddr_in cliaddr, servaddr; + + listenfd = Socket(AF_INET, SOCK_STREAM, 0); + + bzero(&servaddr, sizeof(servaddr)); + servaddr.sin_family = AF_INET; + servaddr.sin_addr.s_addr = htonl(INADDR_ANY); + servaddr.sin_port = htons(SERV_PORT); + + Bind(listenfd, (SA *)&servaddr, sizeof(servaddr)); + + Listen(listenfd, LISTENQ); + + client[0].fd = listenfd; + client[0].events = POLLIN; + for(i = 1; i < OPEN_MAX; i++) + client[i].fd = -1; + maxi = 0; + + + + for(;;) { + nready = Poll(client, maxi + 1, INFTIM); + + if(client[0].revents & POLLIN) { // new client connection + clilen = sizeof(cliaddr); + confd = Accept(listenfd, (SA *) &cliaddr, &clilen); + + for ( i = 0; i < OPEN_MAX; i++) + if(client[i].fd < 0) { + client[i].fd = confd; // save descriptor + break; + } + if( i == OPEN_MAX) + err_quit("too many clients"); + + client[i].events = POLLIN; + + if( i > maxi) + maxi = i; // max index in client[] array + + if(--nready <= 0) + continue; // no more readable descriptor + } + + for(i = 0; i <= maxi; i++) { // check all clients for data + if((sockfd = client[i].fd) < 0) + continue; + if(client[i].revents & (POLLIN | POLLERR)) { + if( (n = Read(sockfd, buf, MAXLINE)) < 0) { + if( errno == ECONNRESET) { + // connection closed by client + Close(sockfd); + client[i].fd = -1; + } else { + err_sys("read error"); + } + } else if(n == 0) { + // connection closed by client + Close(sockfd); + client[i].fd = -1; + } else { + Writen(sockfd, buf, n); + } + + if(--nready <= 0) + break; // no more readable descriptors + } + } + } + +} diff --git a/select/tcpsrvselect01.c b/select/tcpsrvselect01.c new file mode 100644 index 0000000..7989033 --- /dev/null +++ b/select/tcpsrvselect01.c @@ -0,0 +1,78 @@ +#include "unp.h" + + +int main(int argc, char *argv[]) +{ + int listenfd, confd, sockfd, maxfd, maxi, i; + int nready, client[FD_SETSIZE]; + ssize_t n; + fd_set rset, allset; + char buf[MAXLINE]; + socklen_t clilen; + struct sockaddr_in cliaddr, servaddr; + + listenfd = Socket(AF_INET, SOCK_STREAM, 0); + + bzero(&servaddr, sizeof(servaddr)); + servaddr.sin_family = AF_INET; + servaddr.sin_addr.s_addr = htonl(INADDR_ANY); + servaddr.sin_port = htons(SERV_PORT); + + Bind(listenfd, (SA *)&servaddr, sizeof(servaddr)); + + Listen(listenfd, LISTENQ); + + maxfd = listenfd; // initalize + maxi = -1; // index into client[] array + for(i = 0; i maxfd) + maxfd = confd; // for select + if( i > maxi) + maxi = i; // max index in client[] array + + if(--nready <= 0) + continue; // no more readable descriptor + } + + for(i = 0; i <= maxi; i++) { // check all clients for data + if((sockfd = client[i]) < 0) + continue; + if(FD_ISSET(sockfd, &rset)) { + if( (n = Read(sockfd, buf, MAXLINE)) == 0) { + // connection closed by client + Close(sockfd); + FD_CLR(sockfd, &allset); + client[i] = -1; + + } else { + Writen(sockfd, buf, n); + } + + if(--nready <= 0) + break; // no more readable descriptors + } + } + } + +} diff --git a/sockopt/Makefile b/sockopt/Makefile new file mode 100644 index 0000000..aa6a065 --- /dev/null +++ b/sockopt/Makefile @@ -0,0 +1,10 @@ +srcfiles = $(wildcard *.c) +CC = gcc +CFLAGS += -Wall -lunp +objs = $(basename $(srcfiles)) + +all: + @for obj in $(objs); do \ + $(CC) $$obj.c $(CFLAGS) -o build/$$obj; \ + done +.PHONY: all \ No newline at end of file diff --git a/sockopt/checkopts.c b/sockopt/checkopts.c new file mode 100644 index 0000000..551020e --- /dev/null +++ b/sockopt/checkopts.c @@ -0,0 +1,121 @@ +#include "unp.h" +#include + +union val +{ + int i_val; + long l_val; + struct linger linger_val; + struct timeval timeval_val; +} val; + +static char *sock_str_flag(union val *, int); +static char *sock_str_int(union val *, int); +static char *sock_str_linger(union val *, int); +static char *sock_str_timeval(union val *, int); + +static char intres[128]; +static char flagres[256]; +static char lingerres[128]; +static char timevalres[128]; + +struct sock_opts { + const char *opt_str; + int opt_level; + int opt_name; + char *(*opt_val_str)(union val *, int); +} sock_opts[] = { + {"SO_BROADCAST", SOL_SOCKET, SO_BROADCAST, sock_str_flag}, + {"SO_DEBUG", SOL_SOCKET, SO_DEBUG, sock_str_flag}, + {"SO_DONTROUTE", SOL_SOCKET, SO_DONTROUTE, sock_str_flag}, + {"SO_ERROR", SOL_SOCKET, SO_ERROR, sock_str_int }, + {"SO_KEEPALIVE", SOL_SOCKET, SO_KEEPALIVE, sock_str_flag}, + {"SO_LINGER", SOL_SOCKET, SO_LINGER, sock_str_linger}, + {"SO_OOBINLINE", SOL_SOCKET, SO_OOBINLINE, sock_str_flag}, + {"SO_RCVBUF", SOL_SOCKET, SO_RCVBUF, sock_str_int }, + {"SO_SNDBUF", SOL_SOCKET, SO_SNDBUF, sock_str_int }, + {"SO_RCVLOWAT", SOL_SOCKET, SO_RCVLOWAT, sock_str_int }, + {"SO_SNDLOWAT", SOL_SOCKET, SO_SNDLOWAT, sock_str_int }, + {"SO_RCVTIMEO", SOL_SOCKET, SO_RCVTIMEO, sock_str_timeval }, + {"SO_SNDTIMEO", SOL_SOCKET, SO_SNDTIMEO, sock_str_timeval }, + {"SO_REUSEADDR", SOL_SOCKET, SO_REUSEADDR, sock_str_flag}, +// #ifdef SO_REUSEPORT +// {"SO_REUSEPORT", SOL_SOCKET, SO_REUSEPORT, sock_str_flag}, +// #else +// {"SO_REUSEPORT", 0, 0, NULL}, +// #endif + {"SO_TYPE", SOL_SOCKET, SO_TYPE, sock_str_int}, +// #ifdef SO_USELOOPBACK +// {"SO_USELOOPBACK", SOL_SOCKET, SO_USELOOPBACK, sock_str_flag}, +// #else +// {"SO_USELOOPBACK", 0, 0, NULL}, +// #endif + +}; + +int main(int argc, char * argv[]) +{ + int fd; + socklen_t len; + struct sock_opts *ptr; + for( ptr = sock_opts; ptr->opt_str != NULL; ptr++) { + printf("%s: ", ptr->opt_str); + if(ptr->opt_val_str == NULL) + printf("(undefined)\n"); + else { + switch (ptr->opt_level) + { + case SOL_SOCKET: + fd = Socket(AF_INET, SOCK_STREAM, 0); + break; + + default: + err_quit("Can't create fd for level %d\n", ptr->opt_level); + } + } + len = sizeof(val); + if(getsockopt(fd, ptr->opt_level, ptr->opt_name, &val, &len) == -1) { + err_ret("getsockopt error"); + } else { + printf("default = %s\n", (*ptr->opt_val_str)(&val, len)); + } + close(fd); + } +} + + + +char *sock_str_flag(union val *ptr, int len) +{ + if(len != sizeof(int)) + snprintf(flagres, sizeof(flagres), "size(%d) not sizeof(int)", len); + else + snprintf(flagres, sizeof(flagres), "%s", (ptr->i_val == 0)? "off": "on"); + return(flagres); +} + +char *sock_str_int(union val *ptr, int len) +{ + if(len != sizeof(int)) + snprintf(intres, sizeof(intres), "size(%d) not sizeof(int)", len); + else + snprintf(intres, sizeof(intres), "%d", ptr->i_val); + return(intres); + +} +char *sock_str_linger(union val *ptr, int len) +{ + if(len != sizeof(val.linger_val)) + snprintf(lingerres, sizeof(lingerres), "size(%d) not sizeof(linger)", len); + else + snprintf(lingerres, sizeof(lingerres), "l_onoff = %d, l_linger = %d", ptr->linger_val.l_onoff, ptr->linger_val.l_linger); + return(lingerres); +} +char *sock_str_timeval(union val *ptr, int len) +{ + if(len != sizeof(val.timeval_val)) + snprintf(timevalres, sizeof(timevalres), "size(%d) not sizeof(timeval)", len); + else + snprintf(timevalres, sizeof(timevalres), "%ld sec, %ld usec", ptr->timeval_val.tv_sec, ptr->timeval_val.tv_usec); + return(timevalres); +} \ No newline at end of file diff --git a/tcpclisrv/Makefile b/tcpclisrv/Makefile new file mode 100644 index 0000000..aa6a065 --- /dev/null +++ b/tcpclisrv/Makefile @@ -0,0 +1,10 @@ +srcfiles = $(wildcard *.c) +CC = gcc +CFLAGS += -Wall -lunp +objs = $(basename $(srcfiles)) + +all: + @for obj in $(objs); do \ + $(CC) $$obj.c $(CFLAGS) -o build/$$obj; \ + done +.PHONY: all \ No newline at end of file diff --git a/tcpclisrv/tcpcli01.c b/tcpclisrv/tcpcli01.c new file mode 100644 index 0000000..92a9ddd --- /dev/null +++ b/tcpclisrv/tcpcli01.c @@ -0,0 +1,39 @@ +#include "unp.h" + +void str_cli(FILE *, int); + +int main(int argc, char* argv[]) +{ + int sockfd; + struct sockaddr_in servaddr; + + if(argc != 2) + err_quit("usage: tcpcli "); + + sockfd = Socket(AF_INET, SOCK_STREAM, 0); + bzero(&servaddr, sizeof(servaddr)); + servaddr.sin_family = AF_INET; + servaddr.sin_port = htons(SERV_PORT); + Inet_pton(AF_INET, argv[1], &servaddr.sin_addr); + + Connect(sockfd, (SA *) &servaddr, sizeof(servaddr)); + + str_cli(stdin, sockfd); + + exit(0); + +} + +void str_cli(FILE *fp, int sockfd) +{ + char sendline[MAXLINE], recvline[MAXLINE]; + + while(Fgets(sendline, MAXLINE, fp ) != NULL) { + Writen(sockfd, sendline, strlen(sendline)); + + if(Readline(sockfd, recvline, MAXLINE) == 0) + err_quit("str_cli: server terminated prematurely"); + + Fputs(recvline, stdout); + } +} \ No newline at end of file diff --git a/tcpclisrv/tcpcli04.c b/tcpclisrv/tcpcli04.c new file mode 100644 index 0000000..eff3fc8 --- /dev/null +++ b/tcpclisrv/tcpcli04.c @@ -0,0 +1,42 @@ +#include "unp.h" + +void str_cli(FILE *, int); + +int main(int argc, char* argv[]) +{ + int i, sockfd[5]; + struct sockaddr_in servaddr; + + if(argc != 2) + err_quit("usage: tcpcli "); + + for (i = 0; i < 5; i++){ + sockfd[i] = Socket(AF_INET, SOCK_STREAM, 0); + + bzero(&servaddr, sizeof(servaddr)); + servaddr.sin_family = AF_INET; + servaddr.sin_port = htons(SERV_PORT); + Inet_pton(AF_INET, argv[1], &servaddr.sin_addr); + + Connect(sockfd[i], (SA *) &servaddr, sizeof(servaddr)); + } + + str_cli(stdin, sockfd[0]); + + exit(0); + +} + +void str_cli(FILE *fp, int sockfd) +{ + char sendline[MAXLINE], recvline[MAXLINE]; + + while(Fgets(sendline, MAXLINE, fp ) != NULL) { + Writen(sockfd, sendline, strlen(sendline)); + + if(Readline(sockfd, recvline, MAXLINE) == 0) + err_quit("str_cli: server terminated prematurely"); + + Fputs(recvline, stdout); + } +} \ No newline at end of file diff --git a/tcpclisrv/tcpsrv01.c b/tcpclisrv/tcpsrv01.c new file mode 100644 index 0000000..c6f709b --- /dev/null +++ b/tcpclisrv/tcpsrv01.c @@ -0,0 +1,45 @@ +#include "unp.h" + +void str_echo(int); + +int main(int argc, char *argv[]) +{ + int listenfd, confd; + pid_t childpid; + socklen_t clilen; + struct sockaddr_in cliaddr, servaddr; + + listenfd = Socket(AF_INET, SOCK_STREAM, 0); + bzero(&servaddr, sizeof(servaddr)); + servaddr.sin_family = AF_INET; + servaddr.sin_addr.s_addr = htonl(INADDR_ANY); + servaddr.sin_port = htons(SERV_PORT); + Bind(listenfd, (SA *)&servaddr, sizeof(servaddr)); + Listen(listenfd, LISTENQ); + for(;;) { + clilen = sizeof(cliaddr); + confd = Accept(listenfd, (SA *) &cliaddr, &clilen); + if((childpid = Fork()) == 0) { // child process + Close(listenfd); // close listening socket + str_echo(confd); + exit(0); + } + Close(confd); // parent close connected socket + } + +} + +void str_echo(int sockfd) +{ + ssize_t n; + char buf[MAXLINE]; + +again: + while((n = read(sockfd, buf, MAXLINE)) > 0) + Writen(sockfd, buf, n); + + if(n < 0 && errno == EINTR) + goto again; + else if (n < 0) + err_sys("str echo: read error"); +} \ No newline at end of file diff --git a/tcpclisrv/tcpsrv02.c b/tcpclisrv/tcpsrv02.c new file mode 100644 index 0000000..b4530bc --- /dev/null +++ b/tcpclisrv/tcpsrv02.c @@ -0,0 +1,58 @@ +#include "unp.h" + +void str_echo(int); + +void sig_chld(int); + +int main(int argc, char *argv[]) +{ + int listenfd, confd; + pid_t childpid; + socklen_t clilen; + struct sockaddr_in cliaddr, servaddr; + + listenfd = Socket(AF_INET, SOCK_STREAM, 0); + bzero(&servaddr, sizeof(servaddr)); + servaddr.sin_family = AF_INET; + servaddr.sin_addr.s_addr = htonl(INADDR_ANY); + servaddr.sin_port = htons(SERV_PORT); + Bind(listenfd, (SA *)&servaddr, sizeof(servaddr)); + Listen(listenfd, LISTENQ); + Signal(SIGCHLD, sig_chld); + for(;;) { + clilen = sizeof(cliaddr); + confd = Accept(listenfd, (SA *) &cliaddr, &clilen); + if((childpid = Fork()) == 0) { // child process + Close(listenfd); // close listening socket + str_echo(confd); + exit(0); + } + Close(confd); // parent close connected socket + } + +} + +void str_echo(int sockfd) +{ + ssize_t n; + char buf[MAXLINE]; + +again: + while((n = read(sockfd, buf, MAXLINE)) > 0) + Writen(sockfd, buf, n); + + if(n < 0 && errno == EINTR) + goto again; + else if (n < 0) + err_sys("str echo: read error"); +} + +void sig_chld(int signo) +{ + pid_t pid; + int stat; + + pid = wait(&stat); + printf("child %d terminated\n", pid); + return; +} \ No newline at end of file diff --git a/tcpclisrv/tcpsrv03.c b/tcpclisrv/tcpsrv03.c new file mode 100644 index 0000000..3b32756 --- /dev/null +++ b/tcpclisrv/tcpsrv03.c @@ -0,0 +1,63 @@ +#include "unp.h" + +void str_echo(int); + +void sig_chld(int); + +int main(int argc, char *argv[]) +{ + int listenfd, confd; + pid_t childpid; + socklen_t clilen; + struct sockaddr_in cliaddr, servaddr; + + listenfd = Socket(AF_INET, SOCK_STREAM, 0); + bzero(&servaddr, sizeof(servaddr)); + servaddr.sin_family = AF_INET; + servaddr.sin_addr.s_addr = htonl(INADDR_ANY); + servaddr.sin_port = htons(SERV_PORT); + Bind(listenfd, (SA *)&servaddr, sizeof(servaddr)); + Listen(listenfd, LISTENQ); + Signal(SIGCHLD, sig_chld); + for(;;) { + clilen = sizeof(cliaddr); + if((confd = accept(listenfd, (SA *) &cliaddr, &clilen))< 0 ) { + if (errno == EINTR) + continue; // back to for() + else + err_sys("accept error"); + } + if((childpid = Fork()) == 0) { // child process + Close(listenfd); // close listening socket + str_echo(confd); + exit(0); + } + Close(confd); // parent close connected socket + } + +} + +void str_echo(int sockfd) +{ + ssize_t n; + char buf[MAXLINE]; + +again: + while((n = read(sockfd, buf, MAXLINE)) > 0) + Writen(sockfd, buf, n); + + if(n < 0 && errno == EINTR) + goto again; + else if (n < 0) + err_sys("str echo: read error"); +} + +void sig_chld(int signo) +{ + pid_t pid; + int stat; + + pid = wait(&stat); + printf("child %d terminated\n", pid); + return; +} \ No newline at end of file diff --git a/tcpclisrv/tcpsrv04.c b/tcpclisrv/tcpsrv04.c new file mode 100644 index 0000000..5cf0bbd --- /dev/null +++ b/tcpclisrv/tcpsrv04.c @@ -0,0 +1,65 @@ +#include "unp.h" + +void str_echo(int); + +void sig_chld(int); + +int main(int argc, char *argv[]) +{ + int listenfd, confd; + pid_t childpid; + socklen_t clilen; + struct sockaddr_in cliaddr, servaddr; + + listenfd = Socket(AF_INET, SOCK_STREAM, 0); + bzero(&servaddr, sizeof(servaddr)); + servaddr.sin_family = AF_INET; + servaddr.sin_addr.s_addr = htonl(INADDR_ANY); + servaddr.sin_port = htons(SERV_PORT); + Bind(listenfd, (SA *)&servaddr, sizeof(servaddr)); + Listen(listenfd, LISTENQ); + Signal(SIGCHLD, sig_chld); // must call waitpid() + for(;;) { + clilen = sizeof(cliaddr); + if((confd = accept(listenfd, (SA *) &cliaddr, &clilen))< 0 ) { + if (errno == EINTR) + continue; // back to for() + else + err_sys("accept error"); + } + if((childpid = Fork()) == 0) { // child process + Close(listenfd); // close listening socket + str_echo(confd); + exit(0); + } + Close(confd); // parent close connected socket + } + +} + +void str_echo(int sockfd) +{ + ssize_t n; + char buf[MAXLINE]; + +again: + while((n = read(sockfd, buf, MAXLINE)) > 0) + Writen(sockfd, buf, n); + + if(n < 0 && errno == EINTR) + goto again; + else if (n < 0) + err_sys("str echo: read error"); +} + +void sig_chld(int signo) +{ + pid_t pid; + int stat; + + while ((pid = waitpid(-1, &stat, WNOHANG)) > 0) + { + printf("child %d terminated\n", pid); + } + return; +} \ No newline at end of file diff --git a/udpclisrv/Makefile b/udpclisrv/Makefile new file mode 100644 index 0000000..aa6a065 --- /dev/null +++ b/udpclisrv/Makefile @@ -0,0 +1,10 @@ +srcfiles = $(wildcard *.c) +CC = gcc +CFLAGS += -Wall -lunp +objs = $(basename $(srcfiles)) + +all: + @for obj in $(objs); do \ + $(CC) $$obj.c $(CFLAGS) -o build/$$obj; \ + done +.PHONY: all \ No newline at end of file diff --git a/udpclisrv/udpcli01.c b/udpclisrv/udpcli01.c new file mode 100644 index 0000000..e32d5f6 --- /dev/null +++ b/udpclisrv/udpcli01.c @@ -0,0 +1,38 @@ +#include "unp.h" + +void dg_cli(FILE *, int, const SA*, socklen_t); + +int main(int argc, char* argv[]) +{ + int sockfd; + struct sockaddr_in servaddr; + + if(argc != 2) + err_quit("usage: udpcli "); + + bzero(&servaddr, sizeof(servaddr)); + servaddr.sin_family = AF_INET; + servaddr.sin_port = htons(SERV_PORT); + Inet_pton(AF_INET, argv[1], &servaddr.sin_addr); + + sockfd = Socket(AF_INET, SOCK_DGRAM, 0); + + dg_cli(stdin, sockfd, (SA *)&servaddr, sizeof(servaddr)); + + exit(0); + +} + +void dg_cli(FILE *fp, int sockfd, const SA* pservaddr, socklen_t servlen) +{ + int n; + char sendline[MAXLINE], recvline[MAXLINE]; + + while (Fgets(sendline, MAXLINE, fp) !=NULL) { + Sendto(sockfd, sendline, strlen(sendline), 0, pservaddr, servlen); + n = Recvfrom(sockfd, recvline, MAXLINE, 0, NULL, NULL); + recvline[n] = 0; // null terminate + Fputs(recvline, stdout); + } + +} \ No newline at end of file diff --git a/udpclisrv/udpcli02.c b/udpclisrv/udpcli02.c new file mode 100644 index 0000000..acc8f5a --- /dev/null +++ b/udpclisrv/udpcli02.c @@ -0,0 +1,49 @@ +#include "unp.h" + +void dg_cli(FILE *, int, const SA*, socklen_t); + +int main(int argc, char* argv[]) +{ + int sockfd; + struct sockaddr_in servaddr; + + if(argc != 2) + err_quit("usage: udpcli "); + + bzero(&servaddr, sizeof(servaddr)); + servaddr.sin_family = AF_INET; + // servaddr.sin_port = htons(SERV_PORT); + servaddr.sin_port = htons(7); + Inet_pton(AF_INET, argv[1], &servaddr.sin_addr); + + sockfd = Socket(AF_INET, SOCK_DGRAM, 0); + + dg_cli(stdin, sockfd, (SA *)&servaddr, sizeof(servaddr)); + + exit(0); + +} + +void dg_cli(FILE *fp, int sockfd, const SA* pservaddr, socklen_t servlen) +{ + int n; + char sendline[MAXLINE], recvline[MAXLINE]; + socklen_t len; + struct sockaddr *preply_addr; + + preply_addr = Malloc(servlen); + + while (Fgets(sendline, MAXLINE, fp) !=NULL) { + Sendto(sockfd, sendline, strlen(sendline), 0, pservaddr, servlen); + + len = servlen; + n = Recvfrom(sockfd, recvline, MAXLINE, 0, preply_addr, &len); + if(len != servlen || memcmp(pservaddr, preply_addr, len) != 0) { + printf("reply from %s (ignored)\n", Sock_ntop(preply_addr, len)); + continue; + } + recvline[n] = 0; // null terminate + Fputs(recvline, stdout); + } + +} \ No newline at end of file diff --git a/udpclisrv/udpsrv01.c b/udpclisrv/udpsrv01.c new file mode 100644 index 0000000..86ffc6c --- /dev/null +++ b/udpclisrv/udpsrv01.c @@ -0,0 +1,38 @@ +#include "unp.h" + +void dg_echo(int, SA*, socklen_t); + +int main(int argc, char* argv[]) +{ + int sockfd; + struct sockaddr_in servaddr, cliaddr; + + sockfd = Socket(AF_INET, SOCK_DGRAM, 0); + + bzero(&servaddr, sizeof(servaddr)); + servaddr.sin_family = AF_INET; + servaddr.sin_addr.s_addr = htonl(INADDR_ANY); + servaddr.sin_port = htons(SERV_PORT); + + Bind(sockfd, (SA *)&servaddr, sizeof(servaddr)); + dg_echo(sockfd, (SA *)&cliaddr, sizeof(cliaddr)); +} + +void dg_echo(int sockfd, SA *pcliaddr, socklen_t clien) +{ + int n; + socklen_t len; + char msg[MAXLINE]; + char res[MAXLINE]; + char greeting[] = "This is from server: "; + + for(;;) { + len = clien; + + n = Recvfrom(sockfd, msg, MAXLINE, 0, pcliaddr, &len); + strcpy(res, ""); + strncat(res, greeting, strlen(greeting)); + strncat(res, msg, n); + Sendto(sockfd, res, strlen(res), 0, pcliaddr, len); + } + } \ No newline at end of file