ファイナンス、情報通信技術のスキル・アグリゲーション・サイト
「ソケット・プログラミング」の Python プログラムサンプルです。異なるプログラム言語間であっても、ソケット通信を試すことができます。IPv4、IPv6 の両方で接続を受け入れます。
getaddrinfo() で取得したすべてのアドレスについて、ソケットの生成を行います。なお、IPv6 をサポートするソケットは、setsockopt() で IPV6_ONLY ソケット・オプションを設定します。
select() にて、接続要求を待ちます。
「ソケット・プログラミング」は、さまざまなオペレーティング・システム(OS)上で、さまざまなプログラミング言語がサポートしている TCP/IP ネットワーク上のアプリケーションやプロセスを作成することができます。ネットワーク上にあるマシン間のみならず、同一マシン内のプロセス間の通信にも利用されます。
getaddrinfo() から取得したアドレスで順番にソケットを生成します。
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import socket
import select
import sys
HOST = None
PORT = 8888
BACKLOG = 5
BUFSIZE = 1024
sock = None
sockets = []
for res in socket.getaddrinfo(HOST, PORT, socket.AF_UNSPEC, socket.SOCK_STREAM, 0, socket.AI_PASSIVE):
af, socktype, proto, canonname, sa = res
try:
sock = socket.socket(af, socktype, proto)
except OSError as msg:
sock = None
continue
try:
if af == socket.AF_INET6:
sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 1)
if af == socket.AF_INET or af == socket.AF_INET6:
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(sa)
sock.listen(BACKLOG)
sockets.append(sock)
except OSError as msg:
sock.close()
sock = None
continue
if not sockets:
print('could not open socket')
sys.exit(1)
conn = None
try:
while True:
rfds = list(sockets)
rrdy, wrdy, err = select.select(rfds, [], [])
for sock in rrdy:
if sock in sockets:
conn, addr = sock.accept()
print('Connected by', addr)
while True:
data = conn.recv(BUFSIZE)
if not data: break
conn.send(data)
conn.close()
conn = None
finally:
if conn is not None:
conn.close()
for sock in sockets:
sock.close()
getaddrinfo() から取得したアドレスで順番に接続を試みます。
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import socket
import sys
HOST = 'localhost'
PORT = 8888
BUFSIZE = 1024
message = 'send to message'
sock = None
for res in socket.getaddrinfo(HOST, PORT, socket.AF_UNSPEC, socket.SOCK_STREAM):
af, socktype, proto, canonname, sa = res
try:
sock = socket.socket(af, socktype, proto)
except OSError as msg:
sock = None
continue
try:
sock.connect(sa)
except OSError as msg:
sock.close()
sock = None
continue
break
if sock is None:
print('could not open socket')
sys.exit(1)
sock.send(message)
data = sock.recv(BUFSIZE)
print('Received:', data)
sock.close()
getaddrinfo() から取得したアドレスで順番にソケットを生成します。
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import socket
import select
import sys
HOST = None
PORT = 8888
BUFSIZE = 1024
sock = None
sockets = []
for res in socket.getaddrinfo(HOST, PORT, socket.AF_UNSPEC, socket.SOCK_DGRAM, 0, socket.AI_PASSIVE):
af, socktype, proto, canonname, sa = res
try:
sock = socket.socket(af, socktype, proto)
except OSError as msg:
sock = None
continue
try:
if af == socket.AF_INET6:
sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 1)
if af == socket.AF_INET or af == socket.AF_INET6:
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(sa)
sockets.append(sock)
except OSError as msg:
sock.close()
sock = None
continue
if not sockets:
print('could not open socket')
sys.exit(1)
try:
while True:
rfds = list(sockets)
rrdy, wrdy, err = select.select(rfds, [], [])
for sock in rrdy:
if sock in sockets:
data, addr = sock.recvfrom(BUFSIZE)
print('Recieved from', addr)
sock.sendto(data, addr)
finally:
for sock in sockets:
sock.close()
getaddrinfo() から取得したアドレスで順番に送信を試みます。
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import socket
import sys
HOST = 'localhost'
PORT = 8888
BUFSIZE = 1024
message = 'send to message'
sock = None
for res in socket.getaddrinfo(HOST, PORT, socket.AF_UNSPEC, socket.SOCK_DGRAM):
af, socktype, proto, canonname, sa = res
try:
sock = socket.socket(af, socktype, proto)
except OSError as msg:
sock = None
continue
try:
sock.sendto(message, sa)
except OSError as msg:
sock.close()
sock = None
continue
break
if sock is None:
print('could not open socket')
sys.exit(1)
data, addr = sock.recvfrom(BUFSIZE)
print('Received:', data)
sock.close()