2016-10-19 19 views
2

私の質問には、コンピューティングの学生が初めてPythonを使い始めました。これまでは、主にJavaで作業していましたが、今はJavaの規約やプラクティスに最も慣れています。ソケットプログラミングのためのPython 3ソケットプログラミング:sendallとsendtoの使用

背景

割り当ては、我々はマシン上でローカルにサーバとクライアント間で文字列を送信することを要求します。サーバーとクライアントをインスタンス化するサンプル(Python 2)コードが提供されています。割り当ての文脈の外で、私はまた、Pythonの3で動作します。このコードのバージョンを作成したいが、私は、サーバーとクライアント を変更し、クライアントを取得問題は、Python 3

で同じよ​​うに機能するために持っていました

元々、サーバーはほとんど変更を必要とせず、動作させることができました。

#!/usr/bin/python3 

import socket 

HOST='' 
PORT=5870 

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
sock.bind((HOST, PORT)) 
sock.listen(1) 
conn, addr = sock.accept() 

print('Connected by ', addr) 
conn.sendto("Welcome to the server!", (HOST, PORT)) 

while True: 
    data = conn.recv(1024) 
    if not data: break 
    conn.sendall(data) 

conn.close() 

私は、Python 3内で実行され、関数は、私が問題に深く掘りしようとしたことをコーディングするクライアント側を変換することができないんだけど、他のオンラインリソース次のようにサーバーのための私のコードです私にとっては(少なくとも私の経験レベルでは)役に立たない。私のサーバーコードは以下の通りです。

#!/usr/bin/python3 

import socket 

HOST='127.0.0.1' 
PORT=5870 

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
sock.connect((HOST, PORT)) 
data = sock.recv(1024) 
print('Server sent', data) 

sock.sendto("Hello world".encode(), (HOST, PORT)) 

data = sock.recv(1024) 
print("Server sent", data) 

sock.sendto("This is the second message".encode(), (HOST, PORT)) 
data = sock.recv(1024) 
print('Server sent ', data) 

sock.close() 

実際の問題

はもともと、サーバーとクライアントの両方のために、このコードはsendall()の代わりsendto()を使用しますが、私は、クライアントにTypeErrorを取得し、this questionを読んだ後、それを変更しました。私はまだこれがなぜ機能するのか、なぜこれをやらなければならないのか正確にはわかりません(説明は分かりますが)。

クライアントコードを実行すると、sendto()を使用していても、サーバー上に同じTypeErrorが表示されますが、この問題をPython 3で解決する方法がわかりません。受信したスタックトレース私は、Python 3でこの作業を取得することができ

$ python3 mail_server.py 
Connected by ('127.0.0.1', 41866) 
Traceback (most recent call last): 
    File "mail_server.py", line 14, in <module> 
    conn.sendto("Welcome to the server!", (HOST, PORT)) 
TypeError: a bytes-like object is required, not 'str' 
私が間違っているのは何

、どのようにしています:サーバー用に(私は、クライアント上で壊れたパイプを得る)、次のように?私の問題の一部は、この変更がなぜ始まる必要があるのか​​見ていないと思うので、これがなぜ有用であるのかに関する背景的な背景。ありがとう!

+1

'ののsendto()'ソケットをストリーム、データグラムソケット用ではありません。ストリームソケットでは、ストリームが特定のエンドポイントにすでに接続されているため、送信先を指定する必要はありません。 – Barmar

+0

@Barmar私は見る。では、このプログラムのアプリケーション用にストリームソケットを作成するにはどうすればいいですか?何か別のものがあるのでしょうか?それとも、私が望むように 'sendall()'を使って変更する必要がありますか? – jflory7

+2

'sock.accept()'はストリームソケットを返します。特別な処理は必要ありません。 – Barmar

答えて

1

ストリームソケットでsendto()を使用しないでください。ソケットが接続されると(接続後までデータ転送を行うことはできません)、宛先を指定することはできず、接続先のリモートアドレス/ポートに送信されます。

のでsend()またはsendall()を使用します。

socket.sendall("Hello world".encode()); 
関連する問題