https://www.runoob.com/manual/lua53doc/manual.html#6.4.2
<: 设为小端编码
>: 设为大端编码
=: 大小端遵循本地设置
![n]: 将最大对齐数设为 n (默认遵循本地对齐设置)
b: 一个有符号字节 (char)
B: 一个无符号字节 (char)
h: 一个有符号 short (本地大小)
H: 一个无符号 short (本地大小)
l: 一个有符号 long (本地大小)
L: 一个无符号 long (本地大小)
j: 一个 lua_Integer
J: 一个 lua_Unsigned
T: 一个 size_t (本地大小)
i[n]: 一个 n 字节长(默认为本地大小)的有符号 int
I[n]: 一个 n 字节长(默认为本地大小)的无符号 int
f: 一个 float (本地大小)
d: 一个 double (本地大小)
n: 一个 lua_Number
cn: n字节固定长度的字符串
z: 零结尾的字符串
s[n]: 长度加内容的字符串,其长度编码为一个 n 字节(默认是个 size_t) 长的无符号整数。
x: 一个字节的填充
Xop: 按选项 op 的方式对齐(忽略它的其它方面)的一个空条目
' ': (空格)忽略
比如
local text2 = "123456789012"
-- " > " 代表大端 s2表示加上2字节的头部长度 表示unsigned short
local text = string.pack(">s2", text2)
string.pack (fmt, v1, v2, ···)
返回一个打包了(即以二进制形式序列化) v1, v2 等值的二进制字符串。 字符串 fmt 为打包格式(参见 §6.4.2)。
string.unpack (fmt, s [, pos])
返回以格式 fmt (参见 §6.4.2) 打包在字符串 s (参见 string.pack) 中的值。 选项 pos(默认为 1 )标记了从 s 中哪里开始读起。 读完所有的值后,函数返回 s 中第一个未读字节的位置。
lua客户端
local socket = require("socket")
local host = "127.0.0.1"
local port = 9999
local sock = assert(socket.connect(host, port))
print("connect ok")
function m_send(buf)
local text = string.pack(">s2", buf)--加上2字节的头部
sock:send(text)
end
function m_recv1(buf)
local text = string.unpack(">s2", buf, 1);
return text
end
function m_recv2(buf)
--取得头部2字节的内容,此为后续数据的长度
local s = buf:byte(1) * 256 + buf:byte(2)
--不足以一个包
if #buf < (s+2) then
return nil
end
--完整包
return buf:sub(3, 2+s)
end
local msg = "hello world"
m_send(msg)
local t ,status , buf = sock:receive()
--print(sock:receive())
local data = m_recv2(buf)
print(data)
data = m_recv1(buf)
print(data)
C服务端
#include
#include
#include
#include
#include
#include
#define SIZE 300
int main(int argc,char *argv[])
{
int server_sock,client_sock,r;
struct sockaddr_in server_addr,client_addr;
socklen_t len;
server_sock = socket(AF_INET,SOCK_STREAM,0);
//在bind前,设置端口复用设置地址复用 bind error: : Address already in use
const int on=1;
if (setsockopt(server_sock,SOL_SOCKET,SO_REUSEADDR,&on,sizeof on))
{
printf("setsockopt\n");
exit(1);
}
memset(&server_addr,0,sizeof server_addr);
server_addr.sin_family=AF_INET;
server_addr.sin_addr.s_addr=htonl(INADDR_ANY);
server_addr.sin_port=htons(9999);
if(-1 == bind(server_sock, (struct sockaddr*)&server_addr,sizeof(server_addr)))
{
printf(" bind error\n");
return -1;
}
if(-1 == listen(server_sock, 10))
{
printf(" listen error\n");
return -1;
}
char *buf = (char*)malloc(200);
if(!buf){
fprintf(stderr,"malloc error");
return 1;
}
memset(&client_addr,0,sizeof client_addr);
len = sizeof client_addr;
client_sock=accept(server_sock,(struct sockaddr*)&client_addr,&len);
printf("new client ip: %s ,port: %d\n",
inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port));
memset(buf,0,SIZE);
r = read(client_sock,buf,SIZE-1);
buf[r]='\0';
write(client_sock,buf,r);
//取得头部
unsigned short t = *(unsigned short *)buf;
t = ntohs(t);
printf("head: %u\n",t);
printf("data: %s\n",&buf[2]);
close(client_sock);
close(server_sock);
return 0;
}
结果:
new client ip: 127.0.0.1 ,port: 41394
head: 11
data: hello world
ubuntu@VM-0-14-ubuntu:~/skynet/test$ lua lua_test.lua
connect ok
hello world
hello world