本帖最后由 恋恋鸢羽 于 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()
运行:
出现问题的日志:
因为你使用了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()
|