36049


Pythonです。  
Socketを使用して、受信したテキストをそのまま返すエコーサーバーをつくりました。  
沢山の機器で同時接続させたいので、スレッドを使用したのですが、挙動がおかしいです。

Pythonが初心者ということもあり、様々なサイトを見るも解決できず...  
最後にstack overflowさんにたどり着いた次第です。

環境は  
\- Linux (PuppyLinux 571JP)  
\- Python 2.7.3  
です。

これがエコーサーバーのソースです。

[code]

    #coding: UTF-8
    
    import socket
    import threading
    
    class TestThread(threading.Thread):
        def setSocket(self,c):
            self.c = c
    
        def __init__(self):
            threading.Thread.__init__(self)
    
        def run(self):
            try:
                while True:
                    self.text = c.recv(1024)
                    print self.text
                    c.send(self.text)
            except:
                print "error"
                c.close()
    
    if __name__ == "__main__":
        s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        s.bind(("localhost",8000))
        s.listen(5)
        while True:
            print "wait..."
            c,address = s.accept()
            t1 = TestThread()
            print "Connected! ",address
            t1.setSocket(c)
            t1.start()
    
[/code]

これを実行し、telnetで接続すると

  1. telnet_A 接続
  2. telnet_B 接続
  3. telnet_A 発言 >>こんにちは
  4. Server 受信 << こんにちは
  5. telnet_B 受信 <<こんにちは ←なぜかtelnet_Bに送信される
  6. telnet_A 無反応 ←telnet_Aは何も受信しない
  7. telnet_A 発言 >>おはよう
  8. Server,telnet_A,telnet_B 無反応  
以降telnet_Aは切断していないが、発言しても送信されない

  9. telnet_B 発言 >>こんばんわ

  10. Server 受信 << こんばんわ
  11. telnet_B 受信 << こんばんわ  
・・・以降は会話できる。

  12. telnet_B 切断 telnet終了

  13. Server 改行改行改行・・・・・ ←無限に改行を繰り返す

こんな感じです。  
どこが原因なのでしょうか？


CC BY-SA 3.0
2017-07-02T14:59:16.260
36042
2017-07-03T03:54:56.820
2017-07-02T16:56:14.227
76
24172
question
python socket
Socketを使用したエコーサーバーをマルチスレッドにできない

[code]

    def run(self):
        try:
            while True:
                self.text = c.recv(1024)
                print self.text
                c.send(self.text)
        except:
            print "error"
            c.close()
    
[/code]

`c`にしてしまうと

[code]

    c,address = s.accept()
    
[/code]

こちらの部分の随時上書きされていく最後のソケットを参照してしまうので、`self.c`でアクセスする必要があるのでは？


CC BY-SA 3.0
2017-07-03T00:41:24.983
36049
2017-07-03T01:16:19.930
2017-07-03T01:16:19.930
4236
4236
36042
answer


> 13.Server 改行改行改行・・・・・ ←無限に改行を繰り返す

についてですが、サーバ側でコネクションの切断を検知してループを脱出する必要があるのでは？

`socket.recv()`はコネクションが切断されると[0バイトを返す](https://docs.python.jp/2.7/howto/sockets.html#using-
a-socket)=[空の文字列を返す](https://stackoverflow.com/questions/7174927/when-does-
socket-recvrecv-size-return)ので、例えば次のように書くのはどうでしょうか。
(sayuriさんの回答を踏まえて`self`を付加してあります。)

[code]

    def run(self):
        try:
            while True:
                text = self.c.recv(1024)
                if len(text) == 0: return
                print text
                self.c.send(text)
        except:
            print "error"
        finally:
            self.c.close()
    
[/code]


CC BY-SA 3.0
2017-07-03T03:49:07.987
36055
2017-07-03T03:54:56.820
2017-07-03T03:54:56.820
13199
13199
36042
answer