我在C语言中编写一个简单的IRC客户端程序用于自学教学目的,当从套接字文件描述符中调用读取时,我无法理解read()
函数的行为。
以下代码段工作并打印与运行
相同的输出 $ echo "NICK gertrudes\r\nUSER a 0 * d\r\n" | nc chat.freenode.net 6667
,与目前我的程序打印相同:
while ((n = read(sockfd, buffer, sizeof(buffer)-1)) > 0) {
printf("\nloop\n");
buffer[n] = '\0';
if (fputs(buffer, stdout) == EOF)
error("fputs");
}
if (n < 0)
error("reading from socket");
printf("out of the loop\n");
我无法理解为什么程序永远不会进入最后的printf
调用,而是坐在那里,好像在等待服务器上的更多内容。这是否意味着最后一个回复长于0并且IRC服务器在发送另一个命令之前不会发送任何新内容?
如果是这样(冒这里偏离主题的风险),并且read()
正在阻塞,那么在程序等待该调用返回时,我会在哪里编写向服务器发送命令的逻辑? / p>
答案 0 :(得分:1)
我无法理解的是为什么程序永远不会进入最后的printf调用,而是坐在那里,好像在服务器上等待更多。
从服务器 等待更多。当对等体断开连接时,read()
将返回零,而不是之前。
答案 1 :(得分:0)
尽管你的程序没有完整,但你有一些错误的假设。我们在您的代码中对这些进行评论。
while ((n = read(sockfd, buffer, sizeof(buffer)-1)) > 0) {
如果您计划使用sizeof(buffer)-1
字节填写\0
,最好先阅读\0
,但认为您可以接收来自printf("\nloop\n");
buffer[n] = '\0';
if (fputs(buffer, stdout) == EOF)
套接字,如果你想成为一般,不要以为你总是在阅读文本。许多安全漏洞都来自这样的错误。程序员(错误地)假设数据是ascii文本,有人利用缓冲区溢出(不是这种情况)或非法的东西,提供大量空字符以使其失败。
\n
这是一个非常常见的错误 ...你习惯看到当你在缓冲区末尾放置一个stdio
时,stdio将打印出所有内容,直到最后一个缓冲区一见到它。好吧,为了实现这一点,ioctl(2)
检查描述符是否与终端相关联(通过isatty(3)
调用或调用fflush(3)
)。对于套接字不再适用,因此可能已将缓冲区复制到stdio缓冲区,stdio正在等待缓冲区填充,或者在调用write(2)
发送之前使用 error("fputs");
显式刷新缓冲区它上面的所有数据。
fflush(stdout);
此时执行write(2)
,因此您可以确保在继续之前将所有数据发送给对等方,或者根本不使用stdio(使用简单的select(2)
来电,直到你足够精通准备一个}
if (n < 0)
error("reading from socket");
printf("out of the loop\n");
在套接字上的线程,以便在它准备接受更多数据后立即提供更多数据)
import matplotlib, multiprocessing
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt
def plot():
import matplotlib
fig = matplotlib.pyplot.figure()
fig.show()
plot()
multiprocessing.set_start_method('spawn')
p = multiprocessing.Process(target=plot, args=())
p.start()
raw_input()