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 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
| #include <stdio.h> #include <signal.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/wait.h>
#define PORT 23456 #define SERVER_ADDR "127.0.0.1"
int server_socket,client_socket;
void func_kill(int sig){ // printf("%d ",close(server_socket)); // printf("%d ",close(client_socket)); close(server_socket); close(client_socket); signal(SIGINT,SIG_DFL); exit(3); }
int main(int argc, char *argv[]) { // 俩个子进程 pid1 用于接收 pid2 用于发送 int pid1,pid2; // 等待pid退出信号 int pid_exit_status; // 绑定端口结果 监听端口结果 int Bind_res,Listen_res; // 客户端地址块大小 socklen_t clientaddr_len; // 服务端地址块 客户端地址块 struct sockaddr_in serveraddr,clientaddr; // 存储接受的消息 发送的消息 char recv_msg[100],send_msg[100];
//创建服务socket server_socket = socket(AF_INET,SOCK_STREAM,0); if(server_socket==-1) { perror("The socket is error!\n"); exit(0); }
// 设置端口绑定,取消TIME_WAIT,避免占用 struct linger ling; ling.l_onoff = 1; ling.l_linger = 0; setsockopt(server_socket,SOL_SOCKET, SO_LINGER, &ling, sizeof(ling));
// 设置服务端地址 serveraddr.sin_family = AF_INET; //ipv4 serveraddr.sin_port = htons(PORT); //端口 inet_aton(SERVER_ADDR,&serveraddr.sin_addr); //地址 bzero(serveraddr.sin_zero,8);
//绑定 和 监听 端口 Bind_res = bind(server_socket, (struct sockaddr *)(&serveraddr),sizeof(serveraddr)); if(Bind_res==-1) { perror("The bind is error!\n"); exit(0); } Listen_res = listen(server_socket,2); if(Listen_res==-1) { perror("The listen is error!\n"); exit(0); } printf("server start!\n"); // 捕获 ctrl+c信号 signal(SIGINT,func_kill);
// 子进程pid1用于发送 pid1= fork(); // 用于主进程阻塞 while(1) { if(pid1==0) { //等待连接 clientaddr_len = sizeof(struct sockaddr_in); memset(&clientaddr, '\0', sizeof(struct sockaddr_in)); client_socket = accept(server_socket, (struct sockaddr*)(&clientaddr), &clientaddr_len); if(client_socket == -1) { perror("The accept is error!\n"); exit(0); } else { // 打印连接的子进程ip地址和端口信息 char clntName[1024]; if (inet_ntop(AF_INET, &clientaddr.sin_addr.s_addr, clntName, sizeof(clntName)) != NULL) { printf("connecting client ip: %s port: %d\n", clntName, ntohs(clientaddr.sin_port)); } else { printf("client address get failed\n"); } } printf("client connected success!\n"); // pid2 用于接收 pid2=fork(); if(pid2==0) { // pid2 阻塞 while (1) { // 当子进程pid1检测到client断开连接后,及时退出子进程pid2,关闭socket signal(SIGHUP, func_kill); fgets(send_msg, sizeof(send_msg), stdin); send(client_socket, send_msg, sizeof(send_msg), 0); } }else{ // pid1 阻塞 while (1) { int result = recv(client_socket,recv_msg, sizeof(recv_msg), 0); // 子进程pid1检测到client断开连接 if (result <= 0) { printf("client connect close\n"); close(client_socket); kill(pid2,SIGHUP); break; } // 正常连接 printf("Client:%s",recv_msg); } } } else { // 阻塞父进程,pid1退出了就把父进程也退出 int exit_pid = wait(&pid_exit_status); if (exit_pid == pid1) { // printf("paraent process quit!\n"); close(server_socket); close(client_socket); exit(0); } } } return 0; }
|