- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
免责声明:问题的作者对 Erlang 有一般的了解,对 C 有一定的了解。
我正在阅读 Interoperability Tutorial User Guide现在。我已经成功编译了 complex.c
示例,它可以毫无问题地与 Erlang Port 一起工作。
但是,我想了解实际的 C 代码是如何工作的。我一般理解它:在示例中,它从标准输入读取 2 个字节并检查第一个字节。根据第一个字节,它调用 foo
或 bar
函数。这是我目前对它的理解的极限。
所以,如果我们同时使用 erl_comm.c
:
/* erl_comm.c */
typedef unsigned char byte;
read_cmd(byte *buf)
{
int len;
if (read_exact(buf, 2) != 2)
return(-1);
len = (buf[0] << 8) | buf[1];
return read_exact(buf, len);
}
write_cmd(byte *buf, int len)
{
byte li;
li = (len >> 8) & 0xff;
write_exact(&li, 1);
li = len & 0xff;
write_exact(&li, 1);
return write_exact(buf, len);
}
read_exact(byte *buf, int len)
{
int i, got=0;
do {
if ((i = read(0, buf+got, len-got)) <= 0)
return(i);
got += i;
} while (got<len);
return(len);
}
write_exact(byte *buf, int len)
{
int i, wrote = 0;
do {
if ((i = write(1, buf+wrote, len-wrote)) <= 0)
return (i);
wrote += i;
} while (wrote<len);
return (len);
}
和port.c
:
/* port.c */
typedef unsigned char byte;
int main() {
int fn, arg, res;
byte buf[100];
while (read_cmd(buf) > 0) {
fn = buf[0];
arg = buf[1];
if (fn == 1) {
res = foo(arg);
} else if (fn == 2) {
res = bar(arg);
}
buf[0] = res;
write_cmd(buf, 1);
}
}
每个功能在那里实际做什么? li, len, i, wrote, got
变量的实际用途是什么?
一些更小的问题:
void
?foo()
,如果字节包含十进制数 2,则调用 bar()
。如果不做任何更改,此协议(protocol)可用于调用多达 255 个不同的 C 函数,每个函数只有 1 个参数。对吗?buf
被初始化为 [100]
?最佳答案
这个答案同样被否认(我不是 Erlang 或 C 程序员,我只是碰巧正在阅读相同的 Material )
您的初始模型有点偏差。代码实际工作的方式是从 stdin
读取前两个字节,假设它表示实际消息的长度,然后从 stdin
读取更多字节。在这种特定情况下,实际消息总是两个字节(一个数字对应于一个函数和一个传递给它的整数参数)。
0 - a) read_exact
从 stdin
, read_cmd
读取 len
字节使用 read_exact
首先确定它应该读取多少字节(由前两个字节表示的数字,或者如果可用字节少于两个则不读取),然后读取那么多字节。 write_exact
将len
字节写入stdout
,write_cmd
使用write_exact
输出两个字节长度 header ,后跟适当长度的消息(希望如此)。
0 - b) 我认为 len
已在上面充分介绍。 li
是用于为写入函数生成那个两字节 header 的变量的名称(我无法带您逐步完成位移操作,但最终结果是 len
在发送的前两个字节中表示)。 i
是一个中间变量,其主要目的似乎是确保 write
和 read
不返回错误(如果返回错误,那错误代码作为 read_exact
/write_exact
的结果返回)。 wrote
和 got
跟踪已写入/读取了多少字节,包含循环在它变得大于 len
之前退出。
1 - 其实我不确定。我使用的版本是 int
类型,但其他方面相同。我从 Programming Erlang 的第 12 章中得到了我的而不是您链接的指南。
2 - 没错,但端口协议(protocol)的要点是您可以更改它以发送不同的参数(如果您发送任意参数,它会只使用 C Node 方法而不是端口可能是一个更好的主意)。例如,我 modified it subtly在最近的一篇文章中,它发送一个字符串,因为我只有一个函数想在 C 端调用,从而无需指定函数。我还应该提到,如果您的系统需要调用超过 255 个用 C 编写的不同操作,您可能需要重新考虑它的结构(或者直接将全部九个都用 C 编写)。
3 -完成
read_cmd(byte *buf)
{
int len;
if (read_exact(buf, 2) != 2) // HERE
return(-1); // HERE
len = (buf[0] << 8) | buf[1]; // HERE
return read_exact(buf, len);
}
在read_cmd
函数中
write_cmd(byte *buf, int len)
{
byte li;
li = (len >> 8) & 0xff; // HERE
write_exact(&li, 1); // HERE
li = len & 0xff; // HERE
write_exact(&li, 1); // HERE
return write_exact(buf, len);
}
在 write_cmd
函数中。我认为解释包含在 0 - a)
中;这是一个 header ,它告诉/找出消息的其余部分将有多长(是的,这意味着它只能是有限长度,并且该长度必须可以用两个字节表示)。
4 - 我不完全确定为什么这会成为一个陷阱。愿意详细说明吗?
5 - buf
是一个字节数组,必须明确界定(我认为是出于内存管理目的)。我在这里将“100
”读作“一个大于我们计划容纳的最大消息大小的数字”。实际选择的数字似乎是任意的,似乎任何 4 或更高的数字都可以,但我可以在这一点上得到纠正。
关于C 和 Erlang : Erlang Port example,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10488388/
我正在学习网络和套接字,但有些东西我不明白。我经常听说“TCP端口”但我认为端口与应用层有关(例如 HTTP 服务器为 80)。那你为什么不说“应用程序端口”呢?为什么端口似乎与 TCP 层相关联(它
配置 Nginx 以允许像这样的 DOMAIN:PORT 请求的正确方法是什么: http://example.com:8080/?a=xxx&b=yyy&c=zzz over TCP or UDP
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 这个问题似乎不是关于 a specific programming problem, a software
这是我的 nginx.conf,适用于 https。 如果有人输入 HTTP://dev.local.org:3002,我该如何重定向到 HTTPS://dev.local.org:3002? 这个
我在这方面需要一点帮助,而我对这方面的 RegEx 知识有点欠缺。 我有一个代理列表,我正在尝试解析该列表并将 IP 和端口号与字符串分开。 正在读取的字符串看起来像这样。(示例 1) 121.121
我正在尝试制作一个 Firefox 扩展。我需要与后台脚本 (main.js) 交换数据,所以我尝试使用端口,但它不起作用。 //Content.js self.port.on("alert",fun
我正在学习教程,他们使用命令[[ -z "$PORT" ]] && export PORT=8080我不完全明白它在做什么。我对 bash 命令的了解非常基础,所以我什至不知道用什么谷歌来解决这个问题
我已经阅读了数据表和谷歌,但我仍然不明白。 就我而言,我将 PIC18F26K20 的 PIN RC6 设置为 INPUT 模式: TRISCbits.TRISC6 = 1; 然后我用 PORT 和
我想知道是否可以将公共(public) IP 端口(例如端口 80)映射到 Azure iaas VM 上的不同本地/私有(private) IP 端口(例如端口 81)。我相信这在旧门户中是可行的,
我有一个用 python-twisted 编写的客户端,它将 UDP 数据包发送到 IP aaa.bbb.ccc.ddd 的端口 1234,然后等待响应。我还有用 C-libuv 编写的 UDP 服务
我有一个使用弹性 IP 12.34.56.78 运行的 Amazon EC2 实例。我拥有一个域名 example.com,我已将其设置为指向 EC2 实例。我在 EC2 实例的端口 80 上运行 A
我正在尝试在 AWS Lightsail 上配置网站。我做的第一件事是在 中将端口号从 22 更改为 2200 /etc/ssh/sshd_config ,然后我像这样配置了简单的防火墙 sudo u
几天前才意识到 Docker 似乎绕过了我的 iptable 规则。我对 Docker 和 iptables 的经验并不令人难以置信。最近几天尝试了很多不同的东西。还看到最近的 docker 版本有很
我从他们的website 下载了零层使用以下命令: curl -s https://install.zerotier.com | sudo bash 每当我尝试使用 zerotier cli 时,都会
我是字符串操作的新手,只是试图替换列表中的值。 我试图修复的两个输入是 MCAFEE和 PORT O'BRIAN . 所以我跑 ucwords(strtolower($rawTitle)) .但现在我
我正在使用 SSH 访问我大学的 afs 系统。我喜欢使用 rmate(远程 TextMate),它需要 SSH 隧道,因此我在 .bashrc 中包含了这个别名。 alias sshr=ssh -R
当我使用 Control-C 退出“Heroku Open”(Heroku 工具栏服务器命令)时。我无法重新启动。我收到此错误: /vendor/bundle/gems/puma-2.14.0/lib
我正在发送这样的消息: self.port.emit("nodes_grubed", textNodesValues); 并想对此使用react: worker.port.on("nodes_grub
我正在尝试在此扩展中创建一个函数,该函数将打开具有给定网址的选项卡,并在该选项卡上使用给定文件名运行脚本。该功能大部分工作正常,只是我无法在主脚本和我在新选项卡上运行的脚本之间进行通信(我为此使用了
我在我的 .NET MVC 4 元素中使用 Bootstrap ,我使用 NuGet 导入 Bootstrap 我的元素,我有一个布局页面,我在这个页面中包含 Bootstrap 标签,我的索引页面正
我是一名优秀的程序员,十分优秀!