2016-10-19 15 views
0

私は、クライアントが常にログファイルをチェックするクライアントサーバモデルを持っています。そして、新しいラインがログファイルに入るとすぐに、そのラインをサーバに送ります。tcp pythonソケットホールドコネクション永遠

何とか次のコードを使用してこの問題を解決しました。

server.py

import SocketServer 


class MyTCPSocketHandler(SocketServer.BaseRequestHandler): 

    def handle(self): 
     # self.request is the TCP socket connected to the client 
     data = self.request.recv(1024).strip() 
     print data 
     # process the data.. 


if __name__ == "__main__": 

    HOST, PORT = "localhost", 9999 
    server = SocketServer.TCPServer((HOST, PORT), MyTCPSocketHandler) 
    server.serve_forever() 

client.py

import time 
import socket 


def follow(thefile): 
    thefile.seek(0, 2) 
    while True: 
     line = thefile.readline() 
     if not line: 
      time.sleep(0.1) 
      continue 
     yield line 


def connect_socket(): 
    HOST, PORT = "localhost", 9999 
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 

    sock.connect((HOST, PORT)) 
    return sock 

if __name__ == '__main__': 

    logfile = open("my_log.log") 
    loglines = follow(logfile) 
    for line in loglines: 
     sock = connect_socket() 
     # send data 
     sock.sendall(bytes(line)) 

問題は、私は新しい行を送信するためにconnect_socket()メソッドを呼び出す必要があるたびにあります。

私はかなりこの話題に慣れていますので、誰かが私にこの問題を回避する方法を教えてください。クライアントとサーバー間の接続が確立されたら、サーバーにデータを継続的に送信する必要があります新しい接続を何度も繰り返さずに。

私は一度だけを接続し、それが

socket.error: [Errno 32] Broken pipe

私は以下の通りである従っているいくつかのStackOverflowのリンクを投げていたデータを送信するために同じソケットオブジェクトを使用している場合は、

12、私が見つけた3

ことの一つは、

Broken Pipe occurs when one end of the connection tries sending data while the other end has already closed the connection.

です

どのように接続を両端で開いたままにすることができますか? このユースケースについては、非同期メソッドを使用する必要がありますか?その場合、どのフレームワークがtornadoまたはtwistedと最もよく一致しますか?

+0

TCPソケットサーバーはスレッドソケットサーバーではありません。ほとんどのエラーは 'time.sleep()'です。とても悪い考えです。サーバーはACK(遅延を必要としません)に対する応答を必要とし、コードにイーサネットプロトコルがありません。真のスケルトンを作成する場合、パケットは0.5msの時間で成功しました。ソケットは単方向システムではなく、パケットごとにハードウェアバッファをクリアすることはできません。私の意見は、あなたのプロジェクトが複雑でないWSGIを使用することです。 [これをチェック](https://docs.python.org/2.7/library/wsgiref.html) – dsgdfg

答えて

0

回線が送信された後、クライアントで接続を終了しますが、サーバで接続を終了しないでください。 the docsから

RequestHandler.finish()

Called after the handle() method to perform any clean-up actions required. The default implementation does nothing.

だから、あなたにもfinishを実装する必要がありますし、そこにソケット(self.request)を閉じます。


別のオプションは、クライアントの接続を閉じることではありません。

sock = connect_socket() 
for line in loglines: 
    # send data 
    sock.sendall(bytes(line)) 
sock.sendall(b'bye') # EOF 
sock.close() 

ただし、この場合には、サーバーのコードを変更し、それが複数のクライアントにサービスを提供できることを確認し、それがクローズする際に理解しなければなりませんソケット。これらすべての困難にもかかわらず、それは事を行うのに好ましい方法です。理想的には、確立するのにコストがかかるため、クライアントはセッションごとに1つのTCP接続を持ちます。