服务器程序:tcp_server.c
#include <stdio.h> #include <stdlib.h> #include <strings.h> #include <sys/types.h> #include <sys/socket.h> #include <unistd.h> #include <linux/in.h> #include <signal.h> extern void sig_proccess(int signo); #define BACKLOG 5 /* 侦听队列长度 */ /************************************************* * Function : * Description : 服务端主程序 * Calls : process_conn_server * Called By : * Input : * Output : * Return : *************************************************/ int main(int argc, char *argv[]) { if (argc != 2) { printf("Usage:%s port_number\n", argv[0]); return 1; } int port; int ss, sc; /* ss为服务器的socket描述符,sc为客户端的socket描述符 */ struct sockaddr_in server_addr; /* 服务器地址结构 */ struct sockaddr_in client_addr; /* 客户端地址结构 */ int err; /* 返回值 */ pid_t pid; /* 分叉的进行id */ signal(SIGINT, sig_proccess); signal(SIGPIPE, sig_proccess); /* 建立一个流式套接字 */ ss = socket(AF_INET, SOCK_STREAM, 0); if (ss < 0) { /* 出错 */ printf("socket error\n"); return -1; } //获得输入的端口 port = atoi(argv[1]); /* 设置服务器地址 */ bzero(&server_addr, sizeof(server_addr)); /* 清0 */ server_addr.sin_family = AF_INET; /* 协议族 */ server_addr.sin_addr.s_addr = htonl(INADDR_ANY); /* 本地地址 */ server_addr.sin_port = htons(port); /* 服务器端口 */ /* 绑定地址结构到套接字描述符 */ err = bind(ss, (struct sockaddr *)&server_addr, sizeof(server_addr)); if (err < 0) { /* 出错 */ printf("bind error\n"); return -1; } /* 设置侦听 */ err = listen(ss, BACKLOG); if (err < 0) { /* 出错 */ printf("listen error\n"); return -1; } /* 主循环过程 */ for (;;) { int addrlen = sizeof(struct sockaddr); /* 接收客户端连接 */ sc = accept(ss, (struct sockaddr *)&client_addr, &addrlen); if (sc < 0) { /* 出错 */ continue; /* 结束本次循环 */ } /* 建立一个新的进程处理到来的连接 */ pid = fork(); /* 分叉进程 */ if (pid == 0) { /* 子进程中 */ close(ss); /* 在子进程中关闭服务器的侦听 */ process_conn_server(sc); /* 处理连接 */ } else { close(sc); /* 在父进程中关闭客户端的连接 */ } } }
客户端程序:tcp_client.c
#include <stdio.h> #include <stdlib.h> #include <strings.h> #include <sys/types.h> #include <sys/socket.h> #include <unistd.h> #include <linux/in.h> #include <signal.h> extern void sig_proccess(int signo); extern void sig_pipe(int signo); static int s; void sig_proccess_client(int signo) { printf("Catch a exit signal\n"); close(s); exit(0); } /************************************************* * Function : * Description : 客户端主程序 * Calls : process_conn_client * Called By : * Input : * Output : * Return : *************************************************/ int main(int argc, char *argv[]) { int port; struct sockaddr_in server_addr; /* 服务器地址结构 */ int err; /* 返回值 */ signal(SIGINT, sig_proccess); signal(SIGPIPE, sig_pipe); /* 建立一个流式套接字 */ s = socket(AF_INET, SOCK_STREAM, 0); if (s < 0) { /* 出错 */ printf("socket error\n"); return -1; } /* 将用户输入的字符串类型的IP地址转为整型 */ inet_pton(AF_INET, argv[1], &server_addr.sin_addr); port = atoi(argv[2]); /* 设置服务器地址 */ bzero(&server_addr, sizeof(server_addr)); /* 清0 */ server_addr.sin_family = AF_INET; /* 协议族 */ server_addr.sin_addr.s_addr = htonl(INADDR_ANY); /* 本地地址 */ server_addr.sin_port = htons(port); /* 服务器端口 */ /* 连接服务器 */ connect(s, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)); process_conn_client(s); /* 客户端处理过程 */ close(s); /* 关闭连接 */ }
调用程序:tcp_process.c
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <signal.h> /************************************************* * Function : * Description : 服务器对客户端的处理 * Calls : * Called By : * Input : * Output : * Return : *************************************************/ void process_conn_server(int s) { ssize_t size = 0; char buffer[1024]; /* 数据的缓冲区 */ for (;;) { /* 循环处理过程 */ /* 从套接字中读取数据放到缓冲区buffer中 */ memset(buffer, '0', 1024); size = read(s, buffer, 1024); if (size == 0) { /* 没有数据 */ return; } printf("Server: Client had sent %.2d bytes to me!\n", size - 1); /* 构建响应字符,为接收到客户端字节的数量 */ memset(buffer, '0', 1024); sprintf(buffer, "Client: Server had received %.2d bytes from me!\n", size - 1); write(s, buffer, strlen(buffer) + 1); /* 发给客户端 */ } } /************************************************* * Function : * Description : 客户端的处理过程 * Calls : * Called By : * Input : * Output : * Return : *************************************************/ void process_conn_client(int s) { ssize_t size = 0; char buffer[1024]; /* 数据的缓冲区 */ for (;;) { /* 循环处理过程 */ /* 从标准输入中读取数据放到缓冲区buffer中 */ size = read(0, buffer, 1024); if (size > 0) { /* 读到数据 */ write(s, buffer, size); /* 发送给服务器 */ size = read(s, buffer, 1024); /* 从服务器读取数据 */ write(1, buffer, size); /* 写到标准输出 */ } } } /************************************************* * Function : * Description : * Calls : * Called By : tcp_server.c tcp_client.c * Input : * Output : * Return : *************************************************/ void sig_proccess(int signo) { printf("Catch a exit signal\n"); exit(0); } /************************************************* * Function : * Description : * Calls : * Called By : tcp_server.c tcp_client.c * Input : * Output : * Return : *************************************************/ void sig_pipe(int sign) { printf("Catch a SIGPIPE signal\n"); }
makefile文件:
CC = gcc all:client server client:tcp_process.o tcp_client.o $(CC) -o client tcp_process.o tcp_client.o server:tcp_process.o tcp_server.o $(CC) -o server tcp_process.o tcp_server.o clean: rm -f client server *.o
测试结果:
[root@ShiGuang songjingbing]# ./server 8080
Server: Client had sent 11 bytes to me!
Server: Client had sent 11 bytes to me!
Server: Client had sent 41 bytes to me!
[root@ShiGuang songjingbing]# ./client 192.168.1.123 8080
fsafdsafsaf
Client: Server had received 11 bytes from me!
dfasfdsafsa
Client: Server had received 11 bytes from me!
ddddddddddddddddddddddddddddddddddddddddd
Client: Server had received 41 bytes from me!