socket程式設計點到點通訊
阿新 • • 發佈:2018-11-01
//點到點通訊 //伺服器設計 #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <signal.h> #include <stdlib.h> #include <stdio.h> #include <errno.h> #include <string.h> #define ERR_EXIT(m) \ do \ { \ perror(m); \ exit(EXIT_FAILURE);\ }while(0) void handle(int sig) { exit(EXIT_SUCCESS); } int main(void) { int listenfd;//建立套接字 if((listenfd=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP))<0) /* if((listenfd=socket(PF_INET,SOCK_STREAM<0))<0)*/ ERR_EXIT("socket"); //建立伺服器地址 struct sockaddr_in servaddr; memset(&servaddr,0,sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(5188); servaddr.sin_addr.s_addr = htonl(INADDR_ANY); /*servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");*/ /*inet_aton("127.0.0.1",&servaddr.sin_addr);*/ int on = 1; //為了使伺服器處於TIME_WATTING狀態,能再次繫結地址 if(setsockopt(listenfd,SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))<0) ERR_EXIT("setsockopt"); //繫結地址 if(bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr))<0) ERR_EXIT("bind"); //監聽套接字 if(listen(listenfd,SOMAXCONN)<0)//套接字變為被動套接字 ERR_EXIT("listen"); //存放客戶端地址 struct sockaddr_in peeraddr; socklen_t peerlen =sizeof(peeraddr); int conn;//接受accept的套接字 if((conn=accept(listenfd, (struct sockaddr*)&peeraddr, &peerlen))<0)//套接字變為主動,且以後使用accept返回的套接字; ERR_EXIT("accept"); printf("ip=%s port=%d\n", inet_ntoa(peeraddr.sin_addr), ntohs(peeraddr.sin_port)); pid_t pid; pid=fork(); if(pid==-1) { ERR_EXIT("fork"); } if(pid==0)//傳送的子程序 { signal(SIGUSER1, handler);//接受訊號,執行handler函式 char sendbuf[1024] = {0}; while(fgets(sendbuf,sizeof(sendbuf), stdin) != NULL)//獲得傳送內容 { write(conn,sendbuf, strlen(sendbuf)); memset(sendbuf, 0, sizeof(sendbuf)); } exit(EXIT_SUCCESS); } else{//父程序用來獲取資料 char recvbuf[1024]; while(1) { memset(recvbuf,0,sizeof(recvbuf)); int ret = read(conn, recvbuf, sizeof(recvbuf)); if(ret==-1) { ERR_EXIT("read"); } else if(ret==0) { printf("peer close\n"); break; } fputs(recvbuf,stdout); } kill(pid, SIGUSER1);//發出訊號,消除子程序 exit(EXIT_SUCCESS); } close(conn); close(listenfd); return 0; } //客戶端設計 #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <signal.h> #include <stdlib.h> #include <stdio.h> #include <errno.h> #include <string.h> #define ERR_EXIT(m) \ do \ { \ perror(m); \ exit(EXIT_FAILURE); \ }while(0) void handle(int sig) { exit(EXIT_SUCCESS); } int main(void) { int sock; if((sock=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP))<0) /* if((listenfd=socket(PF_INET,SOCK_STREAM<0))<0)*/ ERR_EXIT("socket"); struct sockaddr_in servaddr; memset(&servaddr,0,sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(5188); /*servaddr.sin_addr.s_addr = htonl(INADDR_ANY);*/ servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); /*inet_aton("127.0.0.1",&servaddr.sin_addr);*/ //發起連線 if(connect(sock,(struct sockaddr*)&servaddr,sizeof(servaddr))<0) ERR_EXIT("connect"); pid_t pid; pid = fork(); if(pid==-1) ERR_EXIT("fork"); if(pid==0) { char recvbuf[1024] = {0}; while(1) { memset(recvbuf, 0, sizeof(recvbuf)); int ret = read(sock, recvbuf, sizeof(recvbuf)); if(ret == -1) { ERR_EXIT("read"); } else if(ret == 0) { printf("peer close\n"); break; } fputs(recvbuf, stdout); } close(sock); kill(getppid(), SIGUSER1);//當子程序退出時,告訴父程序退出 } else { signal(SIGUSER1, handler);//父程序得到訊號進行退出 char sendbuf[1024]={0}; while(fgets(sendbuf,sizeof(sendbuf), stdin) != NULL) { write(sock, sendbuf, strlen(sendbuf)); memset(&sendbuf,0, sizeof(sendbuf)); } close(sock); } return 0; }