컴퓨터 공학과 졸업/소켓 프로그래밍
UDP와TCP 소켓을 모두 사용하는 서버(select를 poll로 바꿔보기,중요)
심재철
2017. 11. 29. 23:14
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | #include <stdio.h> #include <errno.h> #include <stdlib.h> #include <arpa/inet.h> #include <signal.h> #include <sys/socket.h> #include <string.h> #include <netinet/in.h> #include <unistd.h> #define MAXLINE 4096 #define SA struct sockaddr #define max(X,Y) ((X) > (Y) ? (X) : (Y)) #define LISTENQ 5 void str_echo(int sockfd) { ssize_t n; char buf[MAXLINE]; again: while ( (n = read(sockfd, buf, MAXLINE)) > 0) write(sockfd, buf, n); if (n < 0 && errno == EINTR) goto again; else if (n < 0) perror("str_echo: read error"); } void sig_chld(){return;} int main(int argc, char **argv) { int listenfd,connfd,udpfd,nready,maxfdp1; char mesg[MAXLINE]; pid_t childpid; fd_set rset; ssize_t n; socklen_t len; const int on = 1; struct sockaddr_in cliaddr, servaddr; void sig_child(int); /*create listening TCP socket*/ 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(30018); setsockopt(listenfd , SOL_SOCKET, SO_REUSEADDR, &on,sizeof(on)); bind(listenfd,(SA*)&servaddr,sizeof(servaddr)); listen(listenfd,LISTENQ); /*create UDP socket */ udpfd = 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(30018); bind(udpfd,(SA*)&servaddr,sizeof(servaddr)); signal(SIGCHLD, sig_chld); /* must call waitpid() */ FD_ZERO(&rset); maxfdp1 = max(listenfd,udpfd) + 1; for(; ; ) { FD_SET(listenfd,&rset); FD_SET(udpfd,&rset); if( (nready = select(maxfdp1, &rset, NULL,NULL,NULL))<0){ if(errno == EINTR) continue; else perror("select error"); } if(FD_ISSET(listenfd,&rset)){ len = sizeof(cliaddr); connfd = accept(listenfd,(SA*)&cliaddr,&len); if( (childpid = fork() ) == 0){ close(listenfd); str_echo(connfd); exit(0); } close(connfd); } if(FD_ISSET(udpfd,&rset)){ len = sizeof(cliaddr); n = recvfrom(udpfd, mesg, MAXLINE, 0, (SA*) &cliaddr, &len); sendto(udpfd,mesg,n,0,(SA *)&cliaddr,len); } } } | cs |
tcp클라이언트 프로그램
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | #include <stdio.h> #include <errno.h> #include <stdlib.h> #include <arpa/inet.h> #include <signal.h> #include <sys/socket.h> #include <string.h> #include <netinet/in.h> #include <unistd.h> #define SA struct sockaddr #define MAXLINE 4096 void str_cli(FILE *fp, int sockfd) { char sendline[MAXLINE], recvline[MAXLINE]; while(fgets(sendline, MAXLINE, fp) != NULL) { write(sockfd, sendline, strlen(sendline)); if (read(sockfd, recvline, MAXLINE) == 0) perror("str_cli: server terminated prematurely"); fputs(recvline, stdout); } } int main(int argc, char **argv) { int sockfd; struct sockaddr_in servaddr; if (argc != 2) perror("usage: tcpcli <IPaddress>"); sockfd = socket(AF_INET, SOCK_STREAM, 0); bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(30018); inet_pton(AF_INET, argv[1], &servaddr.sin_addr); connect(sockfd, (SA *) &servaddr, sizeof(servaddr)); str_cli(stdin, sockfd); return 0; } | cs |
udp 클라이언트 프로그램
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | #include <stdio.h> #include <errno.h> #include <stdlib.h> #include <arpa/inet.h> #include <signal.h> #include <sys/socket.h> #include <string.h> #include <netinet/in.h> #include <unistd.h> #define SA struct sockaddr #define MAXLINE 4096 void dg_cli(FILE *fp, int sockfd, const SA *pservaddr, socklen_t servlen) { int n; char sendline[MAXLINE], recvline[MAXLINE + 1]; 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); } } int main(int argc, char **argv) { int sockfd; struct sockaddr_in servaddr; if(argc != 2) perror("usage: udpcli <IPaddress>"); bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(30018); 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); } | cs |
tcp 패킷과 udp패킷 모두 잘 처리하는 모습