多客户端与服务器通讯
多客户端与服务器通讯
套接字的初始化:
1 //socket_init.h 文件 2 //***************************************************************************** 3 4 #ifndef SOCKET_INIT_H 5 #define SOCKET_INIT_H 6 7 #include <stdlib.h> 8 #include <unistd.h> // gethostname() 9 #include <string.h> // bzero() 10 #include <netdb.h> // struct hostent 11 #include <netinet/in.h> 12 #include <sys/socket.h> 13 //============================================================================= 14 // 函数声名 15 //============================================================================= 16 void init_sockaddr(struct sockaddr_in *name, 17 const char *hostname, const char *serv); 18 int socket_connect(const char *hostname, const char *serv_port); 19 int make_socket(unsigned short int port); 20 //============================================================================= 21 // 根据指定的端口创建具有通配名的 Internet 套接字 22 //============================================================================= 23 int make_socket(unsigned short int port) 24 { 25 int sock; 26 struct sockaddr_in name; 27 /* 创建套接字 */ 28 sock = socket(AF_INET, SOCK_STREAM, 0); 29 if(sock < 0) 30 { 31 printf("create socket error ...\n"); 32 exit(-1); 33 } 34 /* 命名该套接字 */ 35 name.sin_family = AF_INET; 36 name.sin_port = htons(port); 37 name.sin_addr.s_addr = htonl(INADDR_ANY); 38 if(bind(sock, (struct sockaddr *) &name, sizeof(name)) < 0) 39 { 40 printf("bind error ...\n"); 41 exit(-1); 42 } 43 return sock; 44 } 45 //============================================================================= 46 // 用给定的“主机名”和“端口号”填充 sockaddr_in 结构体 47 //============================================================================= 48 void init_sockaddr(struct sockaddr_in *name, 49 const char *hostname, const char *serv) 50 { 51 struct hostent *hp; 52 const char *host; 53 char myname[256]; 54 /* 对给定主机名的处理 */ 55 if(0 == hostname) 56 { 57 /* 获取当前主机的名字 */ 58 gethostname(myname, sizeof(myname)); 59 host = myname; 60 } 61 else 62 { 63 host = hostname; 64 } 65 /* 获取主机信息 */ 66 hp = gethostbyname(host); 67 if(0 == hp) 68 { 69 printf("Unknown host : %s\n", host); 70 exit(-1); 71 } 72 /* 填充 sockaddr_in 结构体 */ 73 bzero(name, sizeof(struct sockaddr)); /* Set N bytes of S to 0. */ 74 if(hp->h_addrtype == AF_INET) 75 { 76 name->sin_family = AF_INET; 77 /* Copy N bytes of SRC to DEST (like memmove, but args reversed). */ 78 bcopy(hp->h_addr_list[0], &name->sin_addr, hp->h_length); 79 if(0 == serv) 80 name->sin_port = htons(0); 81 else 82 name->sin_port = htons(atoi(serv)); 83 } 84 else 85 { 86 printf("Unknow address type ...\n"); 87 exit(-1); 88 } 89 } 90 //============================================================================= 91 // 创建套接字,并与指定的主机建立连接 92 //============================================================================= 93 int socket_connect(const char *hostname, const char *serv_port) 94 { 95 int sockfd; 96 struct sockaddr_in addr; 97 /* 初始化服务器的 IP 地址和端口 */ 98 init_sockaddr(&addr, hostname, serv_port); 99 /* 创建套接字 */ 100 if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) 101 { 102 printf("Socket error ...\n"); 103 exit(-1); 104 } 105 /* 与服务器建立连接 */ 106 if(connect(sockfd, (sockaddr*)&addr, sizeof(sockaddr)) < 0) 107 { 108 printf("Connect error ...\n"); 109 exit(-1); 110 } 111 return sockfd; 112 } 113 #endif // SOCKET_INIT_H
服务器端程序:
1 //server.cpp 文件 2 //***************************************************************************** 3 4 #include <stdio.h> 5 #include <signal.h> 6 #include "socket_init.h" 7 //============================================================================= 8 // 服务器端程序 9 //============================================================================= 10 int make_socket(unsigned short int port); 11 void work(int client_sockfd); 12 int main() 13 { 14 int server_sockfd, client_sockfd; 15 int client_len; 16 struct sockaddr_in client_address; 17 client_len = sizeof(client_address); 18 /* 根据指定的端口创建具有通配名的 Internet 套接字 */ 19 server_sockfd = make_socket(2012); 20 /* 创建连接队列 */ 21 listen(server_sockfd, 6); 22 /* 忽略子进程的终止信号 */ 23 signal(SIGCHLD, SIG_IGN); 24 while(1) 25 { 26 printf("Server waiting ...\n"); 27 /* 准备接受连接 */ 28 client_sockfd = accept(server_sockfd, (sockaddr*)&client_address, 29 (socklen_t*)&client_len); 30 /* 为连接的客户创建一个子进程 */ 31 if(fork() == 0) 32 { 33 close(server_sockfd); // 关闭监听套接字 34 work(client_sockfd); // 处理 35 close(client_sockfd); // 处理完客户需求 36 exit(0); // 终止子进程 37 } 38 /* 父进程 */ 39 else 40 { 41 close(client_sockfd); // 关闭被连接的套接字 42 } 43 } 44 } 45 void work(int client_sockfd) 46 { 47 char buf[256]; 48 int n; 49 n = read(client_sockfd, buf, sizeof(buf)); // 读 50 buf[n] = 0; 51 write(client_sockfd, buf, n); // 写 52 }
客户端程序:
1 //client.cpp 文件 2 //******************************************************************************* 3 4 #include <stdio.h> 5 #include <string.h> 6 #include "../server/socket_init.h" 7 //============================================================================= 8 // 客户端程序 9 //============================================================================= 10 int socket_connect(const char *hostname, const char *serv_port); 11 int main(int argc, char *argv[]) 12 { 13 int connfd; 14 int n; 15 char buf[256]; 16 strcpy(buf, "huzy hello world ! \nHp+y I will get it !\n"); 17 // 连接到当前服务器的 2012 号端口 18 connfd = socket_connect(0, "2012"); 19 write(connfd, buf, strlen(buf)); 20 n = read(connfd, buf, sizeof(buf)); 21 buf[n] = 0; 22 printf("Read from server : \n%s\n", buf); 23 close(connfd); 24 return 0; 25 }
运行截图:
服务器端程序:
客户端程序: