鱼C论坛

 找回密码
 立即注册
查看: 795|回复: 2

[已解决]python求助socketserver.小哥哥小姐姐们,谁赶紧来解决一下啊

[复制链接]
发表于 2018-8-8 14:43:03 | 显示全部楼层 |阅读模式
3鱼币
本帖最后由 恋恋鸢羽 于 2018-8-8 14:44 编辑

问题描述:
写了一个socketServer服务端.
两个socket客户端
要实现的功能是:
启动服务端,再启动两个客户端(两个客户端代码一样)
连接成功后,两个客户端轮流发送数据给服务端.(注意:一个客户端发数字, 另外一个客户端发字母)

另外:我想把接收数据做一个txt日志并记录收到的内容.

问题:为什么客户端轮流发送,服务端能后根据先后顺序print出收到的数据
       可是,日志里顺序却乱了,根本没有根据先后顺序去记录,而是根据了客户端分组记录了?

求:出现这个问题的原因
求:怎么解决,我要日志按照接收顺序来记录.


最后 求大神改造一下我的代码(服务端,把小白的代码改造的高大上一点)

谢谢小甲鱼
谢谢各位大神
谢谢小哥哥
谢谢小姐姐

代码以及问题截图如下
socketserver:
import socket
import socketserver
import datetime
class MyTCPHandler(socketserver.BaseRequestHandler):
    def handle(self):
        filename = '%s_log.txt'%datetime.datetime.now().strftime('%Y-%m-%d')
        with open(filename,'a') as f:
            #获取客户端连接的时间
            log_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')
            #写入日志:什么时间,客户端addr 已经连接
            f.write(log_time+': 客户端'+str(self.client_address)+'已经连接。\n')
            print(log_time+': 客户端'+str(self.client_address)+'已经连接。\n')
            #开始循环接收数据
            while True:
                try:
                    #接收到数据
                    self.data = self.request.recv(1024).strip()#recv
                    #获取接收数据的时间
                    log_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f:')                  
                    f.write(log_time+' 收到数据【{}】'.format(self.client_address)+str(self.data)+'\n')
                    print(log_time+' 收到数据【{}】'.format(self.client_address)+str(self.data))
                    self.request.send(self.data.upper())
                except ConnectionResetError as e:
                    f.write(log_time+':客户端'+str(self.client_address)+'断开连接。'+str(e)+'\n')
                    print(log_time+':客户端'+str(self.client_address)+'断开连接。'+str(e)+'\n')
                    break
if __name__ =='__main__':
    HOST = socket.gethostbyname(socket.gethostname())
    PORT = 9999
    server = socketserver.ThreadingTCPServer((HOST,PORT),MyTCPHandler)
    server.serve_forever()

客户端(两个客户端一样的):
import socket

client = socket.socket()
HOST = socket.gethostbyname(socket.gethostname())
PORT = 9999
client.connect((HOST,PORT))
while True:
    cmd = input('>>:').strip()
    if len(cmd) ==0:
        continue
    client.send(cmd.encode('utf-8'))
    cmd_res = client.recv(1024)
    print(cmd_res.decode())
client.close()

运行:

1.png
出现问题的日志:
2.png
最佳答案
2018-8-8 14:43:04
因为你使用了with这个函数打开文件的,并且写入数据。
使用with函数不需要自己进行关闭文件,它会自动调用close函数,但是这个操作是在with下面的函数块执行完毕之后,所以在调用close之前,数据都是没有写入到文件的,只是在内存中。
你这个一个服务器同时接受两个客户端发送的数据,根据你的写法是使用的线程进行处理的,所以两个客户端就会创建两个线程来处理连接。
所以这两个线程是分别进行IO操作的,当你关闭一个客户端的时候,就意味着有一个线程结束,这时结束的线程中的with才会调用close命令,将数据写入到文件中。
打个比方:A,B客户端,服务器对应的是线程A和线程B。如果客户端A关闭了,那么服务器的线程A就会结束,这时线程A的log数据才会写入到文件中,因此这时文件中只有线程A的数据。而客户端B没有终止数据传输,因此线程B还是运行的状态,因此线程B不会向文件写入任何东西,只有在客户端B停止,服务器的线程B关闭,这时才会将客户端B发送过来的数据写入到文件中去。
把服务器端的代码进行修改就行了,代码如下:
import socket
import socketserver
import datetime
class MyTCPHandler(socketserver.BaseRequestHandler):
    def handle(self):
        filename = '%s_log.txt'%datetime.datetime.now().strftime('%Y-%m-%d')
        with open(filename,'a') as f:
            #获取客户端连接的时间
            log_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')
            #写入日志:什么时间,客户端addr 已经连接
            f.write(log_time+': 客户端'+str(self.client_address)+'已经连接。\n')
            print(log_time+': 客户端'+str(self.client_address)+'已经连接。\n')
            #开始循环接收数据
        while True:
            try:
                #接收到数据
                self.data = self.request.recv(1024).strip()#recv
                #获取接收数据的时间
                log_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f:')
                with open(filename, 'a') as f:                  
                    f.write(log_time+' 收到数据【{}】'.format(self.client_address)+str(self.data)+'\n')
                print(log_time+' 收到数据【{}】'.format(self.client_address)+str(self.data))
                self.request.send(self.data.upper())
            except ConnectionResetError as e:
                f.write(log_time+':客户端'+str(self.client_address)+'断开连接。'+str(e)+'\n')
                print(log_time+':客户端'+str(self.client_address)+'断开连接。'+str(e)+'\n')
                break

if __name__ =='__main__':
    HOST = socket.gethostbyname(socket.gethostname())
    PORT = 9999
    server = socketserver.ThreadingTCPServer((HOST,PORT),MyTCPHandler)
    server.serve_forever()

最佳答案

查看完整内容

此帖仅作者可见
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2018-8-8 14:43:04 | 显示全部楼层    本楼为最佳答案   
此帖仅作者可见
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com

使用道具 举报

 楼主| 发表于 2018-8-8 16:48:57 | 显示全部楼层
此帖仅作者可见
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-12-22 16:38

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表