Pythonのsoketモジュールを使ってデータのソケット通信を簡単にやってみようと思います。
通常、インターネットサービスはネットワークを使ってデータのやり取りを行っていますが、それがどのような仕組みで動いているのかというところまでは、利用する側としてはほとんど気にする必要がありません。
ですが、実際にどんなやりとりをしているのか、クライアントサーバーで見ておくのも何かネットワーク上のエラーがあった時などに役に立つこともあると思うので、簡単なデータのやり取りのコードをUDPとTCPについて書いていきましょう。
ポート番号
インターネットの通信にはポート番号が必要となりますが、ポート番号には、下記のような三つの種別があります。
- WELL KNOWN PORT NUMBERS(ウェルノウンポート番号)
0番~1023番 - REGISTERED PORT NUMBERS(登録ポート番号)
1024番~49151番 - DYNAMIC AND/OR PRIVATE PORTS(ダイナミック/プライベートポート番号)
49152番~65535番
ウェルノウンポート番号はすでに使用目的がIANAによって決められたポート番号で、勝手に使うことはできません。80番などはよく通信で見かけると思います。
登録ポート番号は、使用をIANAに登録して公開される番号で、ここを利用するとバッティングすることもあるので自由には使えません。
ダイナミック/プライベートポート番号は誰でも自由に使用できるポートとして開放されています。
ポート番号の一覧はIANAのWebサイトで公開されていますし、ネットで検索しても色々な解説があります。
ここではもちろんプライベートポート番号を使っていきます。
UDPでsocket通信
ここではパソコン内(私の場合はMac)のローカルホストとして127.0.0.1のIPアドレスと、プライベートポート番号は50000番を利用して通信を行ってみようと思います。
まず、UDPを使ってsocket通信をやってみましょう。
UDPは、「User Datagram Protocol」の略です。 インターネット・プロトコル(IP)を使ったネットワークで、 最小限の仕組みでデータを送受信できるシンプルなプロトコルです。
まずはserver側のコードを書いていきましょう。ここではファイル名をudp_server.pyとしておきます。
from datetime import datetime
import socket
print('The server started at', datetime.now())
print('Waiting...')
server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server.bind(('127.0.0.1', 50000))
data, addr = server.recvfrom(1024)
print('at', datetime.now(),'data: ', data, 'addr: ', addr)
server.close()
コードを上から順に見ていきましょう。
まず、socketモジュールをインポートします。ここではdatetimeモジュールも合わせてインポートしています。
printでサーバーが起動したことをdatetimeモジュールを使って時刻と共に表示し、応答を待つ意味でWaiting…と表示しています。
socket.socket()でソケットを作ります。AF_INETはインターネット接続を示し、SOCK_DGRAMはUDP接続をサポートするソケットタイプです。
次にbind()でサーバーのIPを指定し届いたあらゆるデータを結びつけます(リスンします)。バインドすると言ったりします。サーバーとポート番号はローカルサーバーなので(‘127.0.0.1’, 50000)とここではしておきます。
recvfrom()でデータを受け取ります。ここではデータサイズを1024としておきます。受け取ったデータをdata、addrで持ちます。そして受け取ったデータをprintで出力して、close()でサーバーを閉じます。
次はclient側のコードを書いていきましょう。ここではファイル名をudp_client.pyとしておきます。
from datetime import datetime
import socket
print('The client started at', datetime.now())
client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
client.sendto(b'Hello UDP', ('127.0.0.1', 50000))
client.close()
同様に上から見ていきます。
こちらもまずsocketモジュールをインポートします。ここでもdatetimeモジュールも合わせてインポートしています。
printでクライアントが起動したことを時刻と共に表示します。
socket.socket()でソケットを作るのはサーバーの時と同様です。
sendto()でデータを送ります。データは「Hello UDP」の文字列を送信することにします。バイト型データで送信する必要があるので最初にbをつけています。送信先のサーバーは(‘127.0.0.1’, 50000)として与え、close()で閉じます。
これで準備ができました。
ターミナルを使ってソケット通信を行ってみましょう。
ターミナルをサーバー側とクライアント側として2つ起動してみます。
ここでは左側がサーバー、右側がクライアントです。(ちょっと表示が小さくて申し訳ありません)
サーバー側を実行してみます。
ちょっと字が小さいですけど、サーバーが起動し、Waiting…と表示されて、データが届くのを待っている状態です。
右側のクライアントを実行します。
右側のクライアントが実行されました。すると左側のサーバーがデータを受け取って結果が表示されているのがわかります。
これでUDPを使ったsocket通信ができました。
TCPでsocket通信
次は、TCPを使ってsocket通信をやってみましょう。
TCPは、「Transmission Control Protocol」の略で、インターネットにおいて標準的に利用されているプロトコルです。
こちらもserver側のコードから書いていきましょう。ここではファイル名をtcp_server.pyとしておきます。
from datetime import datetime
import socket
print('The server started at', datetime.now())
print('Waiting...')
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind(('127.0.0.1', 50000))
s.listen(1)
while True:
conn, addr = s.accept()
with conn:
while True:
data = conn.recv(1024)
if not data:
break
print('data: ', data, 'addr: ', addr)
conn.sendall(b'Receive: ' + data)
上から順に見ていきます。モジュールのインポートはこれまでと同様です。
今回はwithステートメントを使ってコードを書いています。(もちろんUDPと同様の書き方もできます)
socket.socket()で同様にソケットを作ります。AF_INETはインターネット接続、SOCK_STREAMはTCP接続をサポートするソケットタイプです。
bind()でサーバーを指定しバインドします。
listen()は接続要求を待つ個数で、ここでは1にしています。
whileで成立している間、accept()でクライアントからの通信を待ちます。
通信が成立したら、こちらはrecv()を使ってデータを取得します。データがなければbreakし、データがあれば受け取ったデータをprintで表示しています。
今回は、sendall()で受け取ったデータをクライアントに返すコードも書いています。
次はclient側のコードを書いていきます。ここではファイル名をtcp_client.pyとしておきます。
from datetime import datetime
import socket
print('The client started at', datetime.now())
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect(('127.0.0.1', 50000))
s.sendall(b'Hello TCP')
data = s.recv(1024)
print(repr(data))
こちらもモジュールのインポートは同様です。
with文で開いていきます。socket.socket()は同様です。
connect()でサーバーに接続します。
sendall()でバイト文字列で「Hello TCP」と送信します。送信部分はここで終了です。
サーバー側で受け取ったデータをクライアントに返すコードを書いているので、クライアント側でもそのデータをrecv()で受け取ります。受け取ったデータをprintで表示します。repr()関数でリテラル表記にして文字列を返しています。
これで準備ができました。
ターミナルを使って同様にソケット通信をしてみましょう。
サーバー側とクライアント側として2つ起動します。
こちらも左側をサーバー、右側をクライアントのターミナルにしています。(表示が小さくて申し訳ない)
左側のサーバーを実行します。
サーバーが起動し、待ち受けになりました。
クライアント側を実行します。
クライアント側が実行されると、サーバー側がデータを受け取ったものが表示されています。
今回のコードではサーバーからデータを受け取ったというコードを書いているので、クライアント側もそれを受け取った表示がなされています。
サーバーを閉じるには、[control]+[C]で終了できます。
これでTCPを使ったsocket通信ができました。
最後に
Pythonのsoketモジュールを使ってデータのソケット通信を簡単にやってみました。
通常、インターネットサービスはネットワークを利用する側としてはデータのやり取りがどのような仕組みで動いているのか気にする必要がありませんが、実際にどんなやりとりをしているのかておくのも何らかネットワーク上のエラーがあった時などに役に立つこともあります。
簡単なデータのやり取りのコードを見ていくのも有益です。
ここでは、UDPとTCPについてのsocket通信を見てきました。
Pythonのsoketモジュールを使ってデータのソケット通信を簡単にやってみようと思います。
通常、インターネットサービスはネットワークを使ってデータのやり取りを行っていますが、それがどのような仕組みで動いているのかというところまでは、利用する側としてはほとんど気にする必要がありません。
ですが、実際にどんなやりとりをしているのか、クライアントサーバーで見ておくのも何かネットワーク上のエラーがあった時などに役に立つこともあると思うので、簡単なデータのやり取りのコードをUDPとTCPについて書いていきましょう。
ポート番号
インターネットの通信にはポート番号が必要となりますが、ポート番号には、下記のような三つの種別があります。
- WELL KNOWN PORT NUMBERS(ウェルノウンポート番号)
0番~1023番 - REGISTERED PORT NUMBERS(登録ポート番号)
1024番~49151番 - DYNAMIC AND/OR PRIVATE PORTS(ダイナミック/プライベートポート番号)
49152番~65535番
ウェルノウンポート番号はすでに使用目的がIANAによって決められたポート番号で、勝手に使うことはできません。80番などはよく通信で見かけると思います。
登録ポート番号は、使用をIANAに登録して公開される番号で、ここを利用するとバッティングすることもあるので自由には使えません。
ダイナミック/プライベートポート番号は誰でも自由に使用できるポートとして開放されています。
ポート番号の一覧はIANAのWebサイトで公開されていますし、ネットで検索しても色々な解説があります。
ここではもちろんプライベートポート番号を使っていきます。
UDPでsocket通信
ここではパソコン内(私の場合はMac)のローカルホストとして127.0.0.1のIPアドレスと、プライベートポート番号は50000番を利用して通信を行ってみようと思います。
まず、UDPを使ってsocket通信をやってみましょう。
UDPは、「User Datagram Protocol」の略です。 インターネット・プロトコル(IP)を使ったネットワークで、 最小限の仕組みでデータを送受信できるシンプルなプロトコルです。
まずはserver側のコードを書いていきましょう。ここではファイル名をudp_server.pyとしておきます。
from datetime import datetime
import socket
print('The server started at', datetime.now())
print('Waiting...')
server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server.bind(('127.0.0.1', 50000))
data, addr = server.recvfrom(1024)
print('at', datetime.now(),'data: ', data, 'addr: ', addr)
server.close()
コードを上から順に見ていきましょう。
まず、socketモジュールをインポートします。ここではdatetimeモジュールも合わせてインポートしています。
printでサーバーが起動したことをdatetimeモジュールを使って時刻と共に表示し、応答を待つ意味でWaiting…と表示しています。
socket.socket()でソケットを作ります。AF_INETはインターネット接続を示し、SOCK_DGRAMはUDP接続をサポートするソケットタイプです。
次にbind()でサーバーのIPを指定し届いたあらゆるデータを結びつけます(リスンします)。バインドすると言ったりします。サーバーとポート番号はローカルサーバーなので(‘127.0.0.1’, 50000)とここではしておきます。
recvfrom()でデータを受け取ります。ここではデータサイズを1024としておきます。受け取ったデータをdata、addrで持ちます。そして受け取ったデータをprintで出力して、close()でサーバーを閉じます。
次はclient側のコードを書いていきましょう。ここではファイル名をudp_client.pyとしておきます。
from datetime import datetime
import socket
print('The client started at', datetime.now())
client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
client.sendto(b'Hello UDP', ('127.0.0.1', 50000))
client.close()
同様に上から見ていきます。
こちらもまずsocketモジュールをインポートします。ここでもdatetimeモジュールも合わせてインポートしています。
printでクライアントが起動したことを時刻と共に表示します。
socket.socket()でソケットを作るのはサーバーの時と同様です。
sendto()でデータを送ります。データは「Hello UDP」の文字列を送信することにします。バイト型データで送信する必要があるので最初にbをつけています。送信先のサーバーは(‘127.0.0.1’, 50000)として与え、close()で閉じます。
これで準備ができました。
ターミナルを使ってソケット通信を行ってみましょう。
ターミナルをサーバー側とクライアント側として2つ起動してみます。
ここでは左側がサーバー、右側がクライアントです。(ちょっと表示が小さくて申し訳ありません)
サーバー側を実行してみます。
ちょっと字が小さいですけど、サーバーが起動し、Waiting…と表示されて、データが届くのを待っている状態です。
右側のクライアントを実行します。
右側のクライアントが実行されました。すると左側のサーバーがデータを受け取って結果が表示されているのがわかります。
これでUDPを使ったsocket通信ができました。
TCPでsocket通信
次は、TCPを使ってsocket通信をやってみましょう。
TCPは、「Transmission Control Protocol」の略で、インターネットにおいて標準的に利用されているプロトコルです。
こちらもserver側のコードから書いていきましょう。ここではファイル名をtcp_server.pyとしておきます。
from datetime import datetime
import socket
print('The server started at', datetime.now())
print('Waiting...')
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind(('127.0.0.1', 50000))
s.listen(1)
while True:
conn, addr = s.accept()
with conn:
while True:
data = conn.recv(1024)
if not data:
break
print('data: ', data, 'addr: ', addr)
conn.sendall(b'Receive: ' + data)
上から順に見ていきます。モジュールのインポートはこれまでと同様です。
今回はwithステートメントを使ってコードを書いています。(もちろんUDPと同様の書き方もできます)
socket.socket()で同様にソケットを作ります。AF_INETはインターネット接続、SOCK_STREAMはTCP接続をサポートするソケットタイプです。
bind()でサーバーを指定しバインドします。
listen()は接続要求を待つ個数で、ここでは1にしています。
whileで成立している間、accept()でクライアントからの通信を待ちます。
通信が成立したら、こちらはrecv()を使ってデータを取得します。データがなければbreakし、データがあれば受け取ったデータをprintで表示しています。
今回は、sendall()で受け取ったデータをクライアントに返すコードも書いています。
次はclient側のコードを書いていきます。ここではファイル名をtcp_client.pyとしておきます。
from datetime import datetime
import socket
print('The client started at', datetime.now())
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect(('127.0.0.1', 50000))
s.sendall(b'Hello TCP')
data = s.recv(1024)
print(repr(data))
こちらもモジュールのインポートは同様です。
with文で開いていきます。socket.socket()は同様です。
connect()でサーバーに接続します。
sendall()でバイト文字列で「Hello TCP」と送信します。送信部分はここで終了です。
サーバー側で受け取ったデータをクライアントに返すコードを書いているので、クライアント側でもそのデータをrecv()で受け取ります。受け取ったデータをprintで表示します。repr()関数でリテラル表記にして文字列を返しています。
これで準備ができました。
ターミナルを使って同様にソケット通信をしてみましょう。
サーバー側とクライアント側として2つ起動します。
こちらも左側をサーバー、右側をクライアントのターミナルにしています。(表示が小さくて申し訳ない)
左側のサーバーを実行します。
サーバーが起動し、待ち受けになりました。
クライアント側を実行します。
クライアント側が実行されると、サーバー側がデータを受け取ったものが表示されています。
今回のコードではサーバーからデータを受け取ったというコードを書いているので、クライアント側もそれを受け取った表示がなされています。
サーバーを閉じるには、[control]+[C]で終了できます。
これでTCPを使ったsocket通信ができました。
最後に
Pythonのsoketモジュールを使ってデータのソケット通信を簡単にやってみました。
通常、インターネットサービスはネットワークを利用する側としてはデータのやり取りがどのような仕組みで動いているのか気にする必要がありませんが、実際にどんなやりとりをしているのかておくのも何らかネットワーク上のエラーがあった時などに役に立つこともあります。
簡単なデータのやり取りのコードを見ていくのも有益です。
ここでは、UDPとTCPについてのsocket通信を見てきました。