自定义C语言网络输出输入工具
一、主要目的
自定义一些C语言网络TCP协议的读写函数,方便输入和输出基本类型。
在内部需要调用sys/socket.h库中的recv()接收和send()发送函数。
本文约定:都是按照大端序来转换取值的。
二、读取函数设计如下
(一)读满数组
// sock是套接字,buff是缓冲数组
// size是目标字节数
// 返回值:读取的字节总数
int readfull(int sock, char buff[], int size){
// MSG_WAITALL是读满才返回
return recv(sock, buff, size, MSG_WAITALL);
}
(二)读1个字节
// sock是套接字
// k是存放字节的变量指针
// 返回值:成功为1,失败为0
int readByte(int sock, int* k){
char buff[2];
// 读取1个字节
int code = readfull(sock, buff, 1);
// 给指针空间赋值
*k = buff[0] & 0xFF;
// 如果个数为1,返回1,否则为0
if(code == 1){
return 1;
}
return 0;
}
(三)读2个字节,转成整数
int read_2byte(int sock, short* k){
char buff[2];
int code = readfull(sock, buff, 2);
// 计算取值
short t = ((0xFF &buff[0]) << 8) | (0xFF & buff[1]);
// 赋值
*k = t;
if(code == 2){
return 1;
}
return 0;
}
(四)读4个字节转成整数
int read_4byte(int sock, int* k){
char buff[5];
int code = readfull(sock, buff, 4);
// 计算取值
int t = 0;
t = t | ((0xFF &buff[0]) << 24);
t = t | ((0xFF & buff[1]) << 16);
t = t | ((0xFF & buff[2]) << 8);
t = t | (0xFF & buff[3]);
// 赋值
*k = t;
if(code == 4){
return 1;
}
return 0;
}
(五)读8个字节,转成整数
int read_long(int sock, long long* k){
char buff[8];
int code = readfull(sock, buff, 8);
long long t = 0;
t = t | ((0xFF & buff[0]) << 56);
t = t | ((0xFF & buff[1]) << 48);
t = t | ((0xFF & buff[2]) << 40);
t = t | ((0xFF & buff[3]) << 32);
t = t | ((0xFF & buff[4]) << 24);
t = t | ((0xFF & buff[5]) << 16);
t = t | ((0xFF & buff[6]) << 8);
t = t | (0xFF & buff[7]);
// 赋值
*k = t;
if(code == 8){
return 1;
}
return 0;
}
(六)读8个字节,转成浮点数
int read_double(int sock, double* k){
char buff[8];
int code = readfull(sock, buff, 8);
long long t = 0;
t = t | ((0xFF & buff[0]) << 56);
t = t | ((0xFF & buff[1]) << 48);
t = t | ((0xFF & buff[2]) << 40);
t = t | ((0xFF & buff[3]) << 32);
t = t | ((0xFF & buff[4]) << 24);
t = t | ((0xFF & buff[5]) << 16);
t = t | ((0xFF & buff[6]) << 8);
t = t | (0xFF & buff[7]);
// 强制把long long*类型转成double*类型
double* p = (double*)&t;
// 赋值
*k = *p;
if(code == 8){
return 1;
}
return 0;
}
三、发送工具函数
(一)发送char变量
int send_1byte(int sock, char k){
return send(sock, &k, 1, 0);
}
(二)发送short变量
int send_2byte(int sock, short k){
char* p = (char*)&k;
return send(sock, p, sizeof(k), 0);
}
(三)发送int整型变量
// sock是套接字, k是整型
// 返回值:成功为1,失败为0
int send_4byte(int sock, int k){
char* p = (char*)&k;
return send(sock, p, sizeof(k), 0);
}
// 第二种方法
int send_4byte(int sock, int k){
char buff[4];
buff[0] = (0xFF000000 & k) >>> 24;
buff[1] = (0xFF0000 & k) >>> 16;
buff[2] = (0xFF00 & k) >>> 8;
buff[3] = (0xFF & k);
// 发送buff中的字节,个数为4
return send(sock, buff, 4, 0);
}
(四)发送long long类型变量
// 返回值:成功为1,失败为0
int send_8byte(int sock, long long k){
char* p = (char*)&k;
return send(sock, p, sizeof(k), 0);
}
(五)发送double类型变量
int send_double(int sock, double k){
char* p = (char*)&k;
return send(sock, p, sizeof(k), 0);
}
(六)发送前缀字符串
格式为: 2字节长度 + 字符串的字节序列
// sock是套接字
// buff存放字符串的字节序列
// size存放长度
// 返回值:发送的字节总数
int send_string(int sock, char buff[], int size){
char temp[2];
// 获得2字节长度
temp[0] = (0xFF00 & size) >>> 8;
temp[1] = (0xFF & size);
// 发送2字节长度
int count = send(sock, temp, 2, 0);
// 发送buff中的字节序列,个数为size
return send(sock, buff, size, 0) + count;
}
四、颠倒一次字节顺序
// buff是字节序列数组
// size是数组元素个数
// 返回值:默认为1
int reverse(char buff[], int size){
char temp = 0;
int k;
for(k = 0; k < size / 2; k++){
temp = buff[k];
buff[k] = buff[size - k - 1];
buff[size - k - 1] = temp;
}
return 1;
}
五、切换字节顺序
(一)把主机序转为网络大端序
// k是被转换的变量
// 返回值:转为大端序的结果
short little_to_big(short k){
// 定义默认值
short temp = 0x0001;
// 转为指针char类型
char* p = (char*)&temp;
// 判断主机的字节顺序
if(*(p+0) == 1){
// 低位地址存放低位字节,是小端序
// 交换一次顺序
short h = k & 0xFF00;
h = h >>> 8;
h = h | ((k & 0xFF) << 8);
return h;
} else {
// 低位地址存放高位字节,是大端序
// 原样返回
return k;
}
}
如果主机本身是小端序就要转换;如果是大端序,就不要转换。
(二)把网络大端序转成主机序
// k是被转换的变量
// 返回值:转为小端序的结果
short big_to_little(short k){
// 定义默认值
short temp = 0x0001;
// 转为指针char类型
char* p = (char*)&temp;
// 判断主机的字节顺序
if(*(p+0) == 1){
// 低位地址存放低位字节,是小端序
// 交换一次顺序
short h = k & 0xFF00;
h = h >>> 8;
h = h | ((k & 0xFF) << 8);
return h;
} else {
// 低位地址存放高位字节,是大端序
// 原样返回
return k;
}
}
说明:两个函数的内部代码是相同的,但是函数名不一样。
更多推荐



所有评论(0)