为啥这会重复打印换行符?

Posted

技术标签:

【中文标题】为啥这会重复打印换行符?【英文标题】:Why does this repeatedly print newline?为什么这会重复打印换行符? 【发布时间】:2012-03-16 13:04:19 【问题描述】:

来自 c 程序的套接字将 3 个数字发送到 python 中的套接字。下面的代码和输出:

python服务器代码:

import SocketServer
import threading
import select
import sys

class TCPHandler(SocketServer.StreamRequestHandler):
    def handle(self):
        self.data = self.rfile.readline()
        print "%s wrote:" % self.client_address[0]
        print (self.data)
        self.request.send(str(long(self.data)+1000))
        cur_connex.append('ip': self.client_address, 'range': [long(self.data), long(self.data)+10000])

        for a in cur_connex:
            print("%s did %d - %d on thread %s" % (a['ip'], a['range'][0], a['range'][1], threading.current_thread().name))

        while True:
            select.select([self.rfile], [], [])
            self.data = self.request.recv(10) #also tried "self.data = self.rfile.readline().strip("\n")" and without "strip()"
            print self.data


if __name__ == "__main__":
    HOST, PORT = "", 50001
    cur_connex = []
    done_up_to = 0

    # Create the server, binding to localhost on port 50001
    server = SocketServer.TCPServer((HOST, PORT), TCPHandler)

    # Activate the server on new thread
    listen_thread = threading.Thread(target=server.serve_forever, name='listen_th')
    listen_thread.start()

c++ 客户端代码:

for(unsigned long long i; i < perfect_numbers.size(); i++)

    cout << "i is " << i << " writing " << perfect_numbers[i] << "\n";

    for(int j = 0; j < perfect_numbers[i].size(); j++)
    
        cout << perfect_numbers[i][j] << "|";
    

    if(write(sock, perfect_numbers[i].c_str(), sizeof(perfect_numbers[i].c_str())) == -1)
    
        cerr << "\nwrite failed: " << strerror(errno) << "\n";
        return -1;
    


if(close(sock) == -1)

    cerr << "close sock error: " << strerror(errno) << "\n";
    return -1;


cout << "exiting...\n";
return 1;

服务器输出:

>>> 127.0.0.1 wrote:
12695

('127.0.0.1', 55624) did 12695 - 22695 on thread listen_th
28
496
8128

...然后是连续的换行符

客户端输出:

that took 1.26624 seconds
i is 0 writing 28

2|8|
|i is 1 writing 496

4|9|6|
|i is 2 writing 8128

8|1|2|8|
|exiting...

我认为 C++ 客户端程序的最后一点就足够了。还假设它在服务器中的 while True 循环中。对这两种语言都是新手,我知道我的编码还不够好,请温柔一点...

【问题讨论】:

【参考方案1】:

这篇文章处理的内容比 OP 所要求的要多,我为这件事道歉。如果您只对如何修复在服务器上编写的待处理换行符感兴趣,请跳转到“python”部分。


客户端/服务器端

您应该在发送/接收的号码之间添加一个分隔符,不能保证每个号码都会单独到达。您可能会在同一次拨打self.request.recv (...) 时收到两个号码。

蟒蛇

print 将在传递给它的每个语句后附加一个换行符 ('\n'),除非您以逗号结束 print 语句。

您应该添加一个检查,看看是否真的有任何数据要读取,如果没有,则可能出现错误或连接已关闭。

while True:
    select.select([self.rfile], [], [self.rfile])
    self.data = self.request.recv(10) 
    if self.data:
       print self.data
    else:
       # <close connection here>

c++

write(sock, perfect_numbers[i].c_str(), sizeof(perfect_numbers[i].c_str()))

无论perfect_numbers[i] 的长度是1 字节还是10 亿字节,上面都会尝试将sizeof(char*) 字符写入套接字sock

write 的第三个参数应该是您希望写入的字节数,因此您应该使用perfect_numbers[i].size ()1


1我假设您在查看以下示例时感到困惑:

 char buf[1024];

 ...

 write (sock, buf, sizeof (buf));

【讨论】:

我认为如果没有可读取的内容,recv() 会被阻止?我还认为选择被阻止,直到有东西要读? @FrederickCraine 如果连接已关闭或容易出错,则有“东西”要读取,但没有数据 - 只是一个必须修复的错误。你是对的,select.select 确实会阻塞,直到有东西要读取,但如果你发送数据的速度比处理它的速度快,你最终会在正在读取的缓冲区中得到多个“块”。【参考方案2】:

查看输出

i 是 0 写 28

2|8*| |*我 ...

我假设 perfect_numbers[i] 以 \n 结尾(在本例中为“28\n”)。列表是如何生成的?

【讨论】:

【参考方案3】:

对于流请求处理程序,self.request 是一个 socket 对象。 socket.recv 函数在套接字关闭时返回一个空字符串。

【讨论】:

以上是关于为啥这会重复打印换行符?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我从 textarea 中提取换行符的方法是使用 \r [重复]

确保每个打印在线程时都在换行符上,在 python 中无限期

Java输出不换行,在固定位置重复打印

Java输出不换行,在固定位置重复打印

为啥cin需要输入换行符? [复制]

Python:避免使用打印命令换行[重复]