tcp客户/服务器回射程序之三-----数据格式
在客户与服务器之间传送的数据格式一般有文本串和2进制结构两种。
1.在客户与服务器之间传送文本串
修改服务器程序,它仍然从客户读入一行文本,不过新的服务器期望该文本行包含有空格分开的两个整数,服务器返回这两个整数的和。不论客户和服务器主机的字节序如何,这个新的客户和服务器程序对都工作的很好。
void str_echo(int sockfd) {
long arg1, arg2;
int n;
char line[500];
for(;;) {
if( (n=readline(sockfd, line, 500)) == 0) {
return;
}
if(sscanf(line, "%ld%ld", &arg1, &arg2) == 2)
snprintf(line, sizeof(line), "%ld\n", arg1+arg2);
else
snprintf(line, sizeof(line), "input error.\n");
n = strlen(line);
write(sockfd, line, n);
}
}
2.在客户和服务器之间传递2进制结构
把客户和服务器程序修改为穿越套接口传递2进制值而不是文本串。当这样的客户和服务器程序运行在字节序不一样的或者所支持长整型的大小不一致的两个主机上时,工作将失常。
struct args {
long arg1, arg2;
};
struct result {
long sum;
};
#include "sum.h"
void str_cli(FILE *fp, int sockfd) {
char sendline[500];
struct args args;
struct result result;
while(fgets(sendline, 500, fp) != NULL) {
if(sscanf(sendline, "%ld%ld", &args.arg1, &args.arg2) != 2) {
printf("invalid input.\n");
continue;
}
write(sockfd, &args, sizeof(args));
if(read(sockfd, &result, sizeof(result)) == 0)
perror("str)cli:server terminated prematurely");
printf("%ld\n", result.sum);
}
}
问题在于由客户以小端字节序格式穿越套接口送出的两个2进制整数,却被服务器解释成了大端字节序整数。本例子实际上存在3个潜在的问题:
1).不同的实现以不同的格式存储2进制。如大端字节序和小端字节序
2).不同的实现在存储相同的c数据类型上可能存在差异。如大多数32位Unix系统使用32位表示长整数,而64位系统却典型的使用64位来表示同样的数据类型。
3).不同的实现给结构打包的方式存在差异,这取决于各种数据类型所用的位数以及机器的对齐方式。
解决这种数据格式问题的两种常用方法:
1).把所有的数值数据作为文本串来传递。当然这里假设客户和服务器主机具有相同的字符集。
2).显示定义所支持数据类型的2进制格式(位数,大端或小端字节序),并以这样的格式在服务器和客户之间传递所有的数据。