2017-02-25 42 views
3

我想使用Python中的只有套接字将图像从客户端上传到服务器。我设计的我怎么也想做到这一点很简单的协议流程:在Python中使用套接字(ONLY)发送图像,图像无法打开

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() 

对于示例图像:

enter image description here

客户端打印出的消息,暗示,它的图像发送到服务器成功:

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() 
+1

未经测试(这就是为什么我没有做这个答案),它看起来像你的服务器获取第一'4096'字节到你的'data'变量,但那些永远不会写进文件。在'elif data:'你用'data = sock.recv(40960000)'覆盖'data',所以第一个'4096'永远不会写入'myfile'文件。也许是吗? – BorrajaX

+0

@BorrajaX:是的,就是这样!我在'myfile = open(basename%imgcounter,'wb')'行后面添加了'myfile.write(data)',现在我可以打开图像! :)但是,它现在看起来很丑(代码)。你有什么想法如何改进它?为了不要有两个'myfile.write(data)'? – yak

+0

@BorrajaX:当客户端发送与'协议'和图像中定义的消息不同的东西时,我该如何避免错误?在这种情况下,我想断开它。 – yak

回答

1

好你的问题是,在实际图像的情况下收到的,你正在阅读的插座两次,第一读忽略的数据,并只是写在第二读取接收到的数据。所以你的图像文件不完整。看到我下面的修复,你可以从这个优化作为出发点。它的工作原理如此。

#!/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()