lua socket客户端 lua string.pack字符串打包

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

你可能感兴趣的:(lua)