Pythonのソケットのみを使用して、クライアントからサーバーに画像をアップロードしたい。私はこれをどのようにしたいかという非常にシンプルなプロトコルフローを設計しました:
CLIENT SERVER
SIZE 512 (send image size)
---------------------------------->
GOT SIZE
<----------------------------------
send image itself
---------------------------------->
GOT IMAGE
<----------------------------------
BYE BYE
---------------------------------->
server closes socket
クライアントコードは次のとおりです。
#!/usr/bin/env python
import random
import socket, select
from time import gmtime, strftime
from random import randint
image = "Tux.png"
Host = '127.0.0.1'
PORT = 6666
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = (Host, PORT)
sock.connect(server_address)
try:
# open image
myfile = open(image, 'rb')
bytes = myfile.read()
size = len(bytes)
# send image size to server
sock.sendall("SIZE %s" % size)
answer = sock.recv(4096)
print 'answer = %s' % answer
# send image to server
if answer == 'GOT SIZE':
sock.sendall(bytes)
# check what server send
answer = sock.recv(4096)
print 'answer = %s' % answer
if answer == 'GOT IMAGE' :
sock.sendall("BYE BYE ")
print 'Image successfully send to server'
myfile.close()
finally:
sock.close()
クライアントから画像を受信するサーバー:
#!/usr/bin/env python
import random
import socket, select
from time import gmtime, strftime
from random import randint
imgcounter = 1
basename = "image%s.png"
Host = '127.0.0.1'
PORT = 6666
connected_clients_sockets = []
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind((Host, PORT))
server_socket.listen(10)
connected_clients_sockets.append(server_socket)
while True:
read_sockets, write_sockets, error_sockets = select.select(connected_clients_sockets, [], [])
for sock in read_sockets:
if sock == server_socket:
sockfd, client_address = server_socket.accept()
connected_clients_sockets.append(sockfd)
else:
try:
data = sock.recv(4096)
txt = str(data)
if txt.startswith('SIZE'):
tmp = txt.split()
size = int(tmp[1])
print 'got size'
sock.send("GOT SIZE")
Elif txt.startswith('BYE'):
sock.shutdown()
Elif data:
myfile = open(basename % imgcounter, 'wb')
data = sock.recv(40960000)
if not data:
myfile.close()
break
myfile.write(data)
myfile.close()
sock.send("GOT IMAGE")
sock.shutdown()
except:
sock.close()
connected_clients_sockets.remove(sock)
continue
imgcounter += 1
server_socket.close()
サンプル画像の場合:
クライアントは、イメージをサーバーに正常に送信することを示唆するメッセージを出力します。
answer = GOT SIZE
answer = GOT IMAGE
Image successfully send to server
画像はサーバー側で作成されますが、開くことができません。そして、はい、私は別の画像を試しました。成功なし。サーバー側で使用できるにもかかわらず、サーバー側で開くことができません。
@BorrajaXのおかげで、なんとか機能させることができました!ありがとう! :)
#!/usr/bin/env python
import random
import socket, select
from time import gmtime, strftime
from random import randint
imgcounter = 1
basename = "image%s.png"
Host = '127.0.0.1'
PORT = 6666
connected_clients_sockets = []
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind((Host, PORT))
server_socket.listen(10)
connected_clients_sockets.append(server_socket)
while True:
read_sockets, write_sockets, error_sockets = select.select(connected_clients_sockets, [], [])
for sock in read_sockets:
if sock == server_socket:
sockfd, client_address = server_socket.accept()
connected_clients_sockets.append(sockfd)
else:
try:
data = sock.recv(4096)
txt = str(data)
if data:
if data.startswith('SIZE'):
tmp = txt.split()
size = int(tmp[1])
print 'got size'
sock.sendall("GOT SIZE")
Elif data.startswith('BYE'):
sock.shutdown()
else :
myfile = open(basename % imgcounter, 'wb')
myfile.write(data)
data = sock.recv(40960000)
if not data:
myfile.close()
break
myfile.write(data)
myfile.close()
sock.sendall("GOT IMAGE")
sock.shutdown()
except:
sock.close()
connected_clients_sockets.remove(sock)
continue
imgcounter += 1
server_socket.close()
問題は、受信した実際の画像の場合、ソケットを2回読み取り、最初の読み取りでデータを無視し、2回目の読み取りで受信したデータを書き込むことです。したがって、画像ファイルは不完全です。以下の私の修正を参照してください、あなたはこれから出発点としてそれを最適化することができます。そのように動作します。
#!/usr/bin/env python
import random
import socket, select
from time import gmtime, strftime
from random import randint
imgcounter = 1
basename = "image%s.png"
Host = '127.0.0.1'
PORT = 6666
connected_clients_sockets = []
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind((Host, PORT))
server_socket.listen(10)
connected_clients_sockets.append(server_socket)
buffer_size = 4096
while True:
read_sockets, write_sockets, error_sockets = select.select(connected_clients_sockets, [], [])
for sock in read_sockets:
if sock == server_socket:
sockfd, client_address = server_socket.accept()
connected_clients_sockets.append(sockfd)
else:
try:
print ' Buffer size is %s' % buffer_size
data = sock.recv(buffer_size)
txt = str(data)
if txt.startswith('SIZE'):
tmp = txt.split()
size = int(tmp[1])
print 'got size'
print 'size is %s' % size
sock.send("GOT SIZE")
# Now set the buffer size for the image
buffer_size = 40960000
Elif txt.startswith('BYE'):
sock.shutdown()
Elif data:
myfile = open(basename % imgcounter, 'wb')
# data = sock.recv(buffer_size)
if not data:
myfile.close()
break
myfile.write(data)
myfile.close()
sock.send("GOT IMAGE")
buffer_size = 4096
sock.shutdown()
except:
sock.close()
connected_clients_sockets.remove(sock)
continue
imgcounter += 1
server_socket.close()