鱼C论坛

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

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

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

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

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

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

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


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

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

代码以及问题截图如下
socketserver:
  1. import socket
  2. import socketserver
  3. import datetime
  4. class MyTCPHandler(socketserver.BaseRequestHandler):
  5.     def handle(self):
  6.         filename = '%s_log.txt'%datetime.datetime.now().strftime('%Y-%m-%d')
  7.         with open(filename,'a') as f:
  8.             #获取客户端连接的时间
  9.             log_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')
  10.             #写入日志:什么时间,客户端addr 已经连接
  11.             f.write(log_time+': 客户端'+str(self.client_address)+'已经连接。\n')
  12.             print(log_time+': 客户端'+str(self.client_address)+'已经连接。\n')
  13.             #开始循环接收数据
  14.             while True:
  15.                 try:
  16.                     #接收到数据
  17.                     self.data = self.request.recv(1024).strip()#recv
  18.                     #获取接收数据的时间
  19.                     log_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f:')                  
  20.                     f.write(log_time+' 收到数据【{}】'.format(self.client_address)+str(self.data)+'\n')
  21.                     print(log_time+' 收到数据【{}】'.format(self.client_address)+str(self.data))
  22.                     self.request.send(self.data.upper())
  23.                 except ConnectionResetError as e:
  24.                     f.write(log_time+':客户端'+str(self.client_address)+'断开连接。'+str(e)+'\n')
  25.                     print(log_time+':客户端'+str(self.client_address)+'断开连接。'+str(e)+'\n')
  26.                     break
  27. if __name__ =='__main__':
  28.     HOST = socket.gethostbyname(socket.gethostname())
  29.     PORT = 9999
  30.     server = socketserver.ThreadingTCPServer((HOST,PORT),MyTCPHandler)
  31.     server.serve_forever()
复制代码


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

  2. client = socket.socket()
  3. HOST = socket.gethostbyname(socket.gethostname())
  4. PORT = 9999
  5. client.connect((HOST,PORT))
  6. while True:
  7.     cmd = input('>>:').strip()
  8.     if len(cmd) ==0:
  9.         continue
  10.     client.send(cmd.encode('utf-8'))
  11.     cmd_res = client.recv(1024)
  12.     print(cmd_res.decode())
  13. 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发送过来的数据写入到文件中去。
把服务器端的代码进行修改就行了,代码如下:
  1. import socket
  2. import socketserver
  3. import datetime
  4. class MyTCPHandler(socketserver.BaseRequestHandler):
  5.     def handle(self):
  6.         filename = '%s_log.txt'%datetime.datetime.now().strftime('%Y-%m-%d')
  7.         with open(filename,'a') as f:
  8.             #获取客户端连接的时间
  9.             log_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')
  10.             #写入日志:什么时间,客户端addr 已经连接
  11.             f.write(log_time+': 客户端'+str(self.client_address)+'已经连接。\n')
  12.             print(log_time+': 客户端'+str(self.client_address)+'已经连接。\n')
  13.             #开始循环接收数据
  14.         while True:
  15.             try:
  16.                 #接收到数据
  17.                 self.data = self.request.recv(1024).strip()#recv
  18.                 #获取接收数据的时间
  19.                 log_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f:')
  20.                 with open(filename, 'a') as f:                  
  21.                     f.write(log_time+' 收到数据【{}】'.format(self.client_address)+str(self.data)+'\n')
  22.                 print(log_time+' 收到数据【{}】'.format(self.client_address)+str(self.data))
  23.                 self.request.send(self.data.upper())
  24.             except ConnectionResetError as e:
  25.                 f.write(log_time+':客户端'+str(self.client_address)+'断开连接。'+str(e)+'\n')
  26.                 print(log_time+':客户端'+str(self.client_address)+'断开连接。'+str(e)+'\n')
  27.                 break

  28. if __name__ =='__main__':
  29.     HOST = socket.gethostbyname(socket.gethostname())
  30.     PORT = 9999
  31.     server = socketserver.ThreadingTCPServer((HOST,PORT),MyTCPHandler)
  32.     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-4-24 08:43

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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