下面编写程序以体验应用层协议的定义过程。该程序中,服务器端从客户端获得多个数字和运算符信息。服务器端收到数字后对其进行加减乘运算,然后把结果传回客户端。例如,向服务器端传递3、5、9的同时请求加法运算,则客户端收到3+5+9的运算结果;若请求做乘法运算,则客户端收到3x5x9的运算结果。而如果向服务器端传递4、3、2的同时要求做减法,则客户端将收到4-3-2的运算结果,即第一个参数成为被减数。
下面的代码与前面的服务器/客户端编程代码总体是一样的。区别在于对发送、接收数据的处理。
服务器端代码
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
| #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <unistd.h> #include <sys/socket.h> #include <string.h> #include <arpa/inet.h>
#define BUF_SIZE 1024 #define NUM_SIZE 4
void error_handling(char *message); int cal(int nun_cnt, int nums[], char op);
int main(int argc, char *argv[]) { int serv_sock, clnt_sock; struct sockaddr_in serv_adr, clnt_adr; socklen_t clnt_adr_len; char message[BUF_SIZE];
if (argc != 2) { printf("Usage: %s <port>\n", argv[0]); exit(1); }
serv_sock = socket(PF_INET, SOCK_STREAM, 0); if (serv_sock == -1) { error_handling("scoket() error!"); }
memset(&serv_adr, 0, sizeof(serv_adr)); serv_adr.sin_family = AF_INET; serv_adr.sin_addr.s_addr = htonl(INADDR_ANY); serv_adr.sin_port = htons(atoi(argv[1]));
if (bind(serv_sock, (struct sockaddr *)&serv_adr, sizeof(serv_adr)) == -1) { error_handling("bind() error!"); }
if (listen(serv_sock, 5) == -1) { error_handling("listen() error!"); }
clnt_adr_len = sizeof(clnt_adr); clnt_sock = accept(serv_sock, (struct sockaddr *)&clnt_adr, &clnt_adr_len); if (clnt_sock == -1) { error_handling("accept() error!"); }
if (read(clnt_sock, &message, NUM_SIZE) == -1) { error_handling("read() error!"); }
int num_cnt = *((int *)&message); int str_len = (1 + num_cnt) * NUM_SIZE + 1; int recv_len = 0, recv_cnt;
while (recv_len + NUM_SIZE < str_len) { recv_cnt = read(clnt_sock, &message[NUM_SIZE * 1], BUF_SIZE - NUM_SIZE); if (recv_cnt == -1) { error_handling("read() error!"); } recv_len += recv_cnt; } int result = cal(num_cnt, (int *)&message[1 * NUM_SIZE], *(char *)&message[(num_cnt + 1) * NUM_SIZE]);
if (write(clnt_sock, &result, sizeof(result)) == -1) { error_handling("write() error!"); }
close(serv_sock); close(clnt_sock);
return 0; }
void error_handling(char *message) { fputs(message, stderr); fputc('\n', stderr); exit(1); }
int cal(int num_cnt, int nums[], char op) { int result = nums[0]; int i;
for (i = 1; i < num_cnt; ++i) { switch (op) { case '+': result += nums[i]; break;
case '-': result -= nums[i]; break;
case '*': result *= nums[i]; break;
case '/': result /= nums[i]; break; } } return result; }
|
客户端代码
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
| #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <unistd.h> #include <sys/socket.h> #include <string.h> #include <arpa/inet.h>
#define BUF_SIZE 1024 #define NUM_SIZE 4
void error_handling(char *message);
int main(int argc, char *argv[]) { int clnt_sock; struct sockaddr_in serv_adr, clnt_adr; char message[BUF_SIZE]; int num_count; int i, result;
if (argc != 3) { printf("Usage: %s <ip> <port>\n", argv[0]); exit(1); }
clnt_sock = socket(PF_INET, SOCK_STREAM, 0);
memset(&serv_adr, 0, sizeof(serv_adr)); serv_adr.sin_family = AF_INET; serv_adr.sin_addr.s_addr = inet_addr(argv[1]); serv_adr.sin_port = htons(atoi(argv[2]));
if (connect(clnt_sock, (struct sockaddr *)&serv_adr, sizeof(serv_adr)) == -1) { error_handling("connect() error!"); }
fputs("请输入操作数的数量:", stdout); scanf("%d", &message); for (i = 0; i < *(int *)&message; ++i) { printf("请输入第 %d 个操作数:", i + 1); scanf("%d", &message[(i + 1) * NUM_SIZE]); } fputs("请输入操作符:", stdout); getchar(); scanf("%c", &message[((*(int *)&message) + 1) * NUM_SIZE]);
if (write(clnt_sock, message, sizeof(message)) == -1) { error_handling("write() error!"); }
if (read(clnt_sock, &result, NUM_SIZE) == -1) { error_handling("read() error!"); }
close(clnt_sock);
printf("the result from server is: %d.\n", result);
return 0; }
void error_handling(char *message) { fputs(message, stderr); fputc('\n', stderr); exit(1); }
|
示例输入输出
1 2
| [root@VM-8-13-centos c]# ./op_server 1233
|
光标会停留在第二个行,处于监听中。
1 2 3 4 5 6 7
| [root@VM-8-13-centos c]# ./op_client 127.0.0.1 1233 请输入操作数的数量:3 请输入第 1 个操作数:11 请输入第 2 个操作数:22 请输入第 3 个操作数:33 请输入操作符:* the result from server is: 7986.
|