我正在尝试制作用于服务在线应用程序的telnet服务器应用程序。该应用程序由xinetd启动,因此该应用程序本身不执行任何网络工作,它像执行其他任何简单的C程序一样仅执行I / O。此应用程序将以类似于FICS的方式工作,这是您可以通过使用Telnet(telnet freechess.org
)连接到其他服务器并与其他人下棋的服务器。
那么,怎么了?
Telnet使用一堆特殊字符组合(例如FF FB 06
)将命令发送到服务器,并且它期望服务器响应这些命令。如果不处理它们,可能会导致不良的用户体验,因为实际的程序将接收并且无法正确处理Telnet命令,从而引起混乱。为了处理这些命令,我决定制作一个位于客户端和实际程序之间的代理程序。代理程序应该从客户端接收输入,并且如果输入是telnet命令,则它应该处理它。否则,应将其发送到实际程序。但是,我不确定如何做这样的事情。我以为posix_spawn
有处理I / O的选项,但我找不到关于此的更多信息。
正在制作这样的程序吗?如果是这样,有人可以指导我吗?我可能可以自己过滤字节,我只需要知道如何在将用户输入发送到实际程序之前对其进行修改。
我自己就能提出解决方案。
首先,我们需要使用pipe()
函数创建管道。这将为我们提供用于读取和写入此管道的文件描述符。
int fds[2];
pipe(fds);
创建此管道后,我们需要进行派生以创建一个新进程。此新过程将成为代理过程。
int child_pid = fork();
if (child_pid < 0) {
// Fork failed
exit(1);
}
else if (child_pid == 0) {
// This is the child
// Close the existing stdin handle
fclose(stdin);
// Close the write handle for the pipe. This won't be used by the child.
close(fds[1]);
// Duplicate the read handle for the pipe. Since file handle 0
// which is normally used for stdin is now unused, calling dup()
// for this file descriptor should duplicate it to file descriptor
// 0.
int new_stdin = dup(fds[0]);
// Reopen the stdin FILE* with this new file descriptor.
stdin = fdopen(0, "r");
// Execute the program that'll be proxied.
execl("/bin/cat", "cat", NULL);
// If execution reaches this point, execl didn't work.
// Kill the parent process and exit.
kill(getppid(), SIGKILL);
exit(1);
}
父级现在要做的就是等待输入并将其发送给子程序。它可以进行所需的任何修改。
// Close the read handle for the pipe. It won't be used by
// the parent process.
close(fds[0]);
// I/O loop
int c;
while ((c = getchar()) != EOF) {
if ((c >= 0) && (c <= 255)) {
if (c == 'l') c = 'w';
char cc = (char)c;
write(fds[1], &cc, 1);
}
}
注意:此答案未包含所有必要的错误处理代码。