【问题标题】:Sending pictures on Socket Python在 Socket Python 上发送图片
【发布时间】:2020-07-25 07:52:23
【问题描述】:

我目前正在做一个项目,我需要通过 Python 将照片发送到另一台计算机。我正在使用模块 Socket,但是当我尝试发送照片时,我收到一条错误消息,提示“发送到数据报套接字的消息大于内部消息缓冲区或另一个网络边界,或者用于接收数据报的缓冲区是小于数据报本身” 我该如何解决? 谢谢

【问题讨论】:

  • 停止尝试将整个内容放入单个数据报中。要么使用流套接字,要么手动将文件分解为多个数据报。如果您的意思是模块socket,那么第一部分的意思是socket.SOCK_STREAM。我不知道一个名为 Socket 的模块,所以我无能为力。
  • 是的,我指的是名为 socket 的模块。但是我用socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) 初始化了我的主套接字。所以我用socket.SOCK_STREAM...

标签: python sockets photo datagram


【解决方案1】:

您的图片太大,无法在一个 UDP 数据包中发送。您需要将图像数据拆分为多个单独发送的数据包。 socket.SOCK_STREAM 而不是 socket.SOCK_DGRAM。在那里,您不必担心数据包大小和排序。虽然你需要设置buffer_size。

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

【讨论】:

  • 感谢您的回答。我在客户端放什么代码?
【解决方案2】:

服务器代码:

import socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(("", 5005))
server_socket.listen(5)
import os


client_socket, address = server_socket.accept()
print "Conencted to - ",address,"\n"
while (1):
    choice = client_socket.recv(1024)
    choice = int(choice)
    if(choice == 1):
        data = client_socket.recv(1024)
        print "The following data was received - ",data
        print "Opening file - ",data
        fp = open(data,'rb')
        strng = fp.read()
        size = os.path.getsize(data)
        size = str(size)
        client_socket.send(size)
        client_socket.send (strng)
        #client_socket.close()

    if (choice == 2 or choice == 3):
        data = client_socket.recv(1024)
        print "The following data was received - ",data
        print "Opening file - ",data
        img = open(data,'rb')
        while True:
            strng = img.read(512)
            if not strng:
                break
            client_socket.send(strng)
        img.close()
        print "Data sent successfully"
        exit()

客户代码:

请参考https://docs.python.org/2/library/socket.html#socket.socket.setblocking 此代码将暂停,直到它接收到数据。默认情况下,所有套接字都处于阻塞模式。你应该让它成为非阻塞的。

在非阻塞模式下,如果一个 recv() 调用没有找到任何数据,或者如果一个 send() 调用不能立即处理数据,错误异常 被提升;在阻塞模式下,调用会阻塞,直到它们可以继续。 s.setblocking(0) 等价于 s.settimeout(0.0); s.setblocking(1) 相当于 s.settimeout(None)。

或者:

把client_socket.settimeout(10.0)放在while(1)之后和client_socket.send(k)之前 在 while(1) -> c,a = client_socket.accept() 之后写 c.settimeout(10.0) -> 然后在任何有client_socket的地方将其更改为“c”

因此:

client_socket.connect(("", 5005))
deadline = time.time() + 20.0
client_socket.settimeout(deadline - time.time())
#or
client_socket.setblocking(0)

所有代码:

import socket,os
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(("", 5005))
client_socket.settimeout(1.0)
k = ' '
size = 1024

while(1):
    print "Do you want to transfer a \n1.Text File\n2.Image\n3.Video\n"
    k = raw_input()
    client_socket.send(k)
    k = int (k)
    if(k == 1):
        print "Enter file name\n"
        strng = raw_input()
        client_socket.send(strng)
        size = client_socket.recv(1024)
        size = int(size)
        print "The file size is - ",size," bytes"
        size = size*2
        strng = client_socket.recv(size)
        print "\nThe contents of that file - "
        print strng

    if (k==2 or k==3):
        print "Enter file name of the image with extentsion (example: filename.jpg,filename.png or if a video file then filename.mpg etc) - "
        fname = raw_input()
        client_socket.send(fname)
        fname = 'documents/'+fname
        fp = open(fname,'w')
        while True:
            try:
                strng = client_socket.recv(512)
                if not strng:
                    break
            except timeout:
                continue
            fp.write(strng)
        fp.close()
        print "Data Received successfully"
        exit()

【讨论】:

  • 您好,这些代码对我不起作用。当我执行它们时,一切正常,但是当图片发送时,它永远不会进入客户端的循环if not strng: break,所以照片没有关闭,我无法打开它。虽然,由于文件不为空,因此可以正确接收数据。谢谢
  • 我真的不知道如何解决它,我尝试了很多方法但仍然无法正常工作
  • 我一直在尝试运行这段代码,但还是不行.....
  • @Armczbt 我刚看到你的评论,抱歉耽搁了。我在客户端编辑了我的答案。正如我提到的,您需要设置超时或将套接字设置为非阻塞,以防止暂停接收文件或图像。希望对您有所帮助,如果它不起作用,请随时询问。
  • client_socket.recv(512) 将被阻止,直到它收到一些东西。如果它什么也没收到,那么它就等待。但是,如果您设置了超时,那么该等待会定期抛出异常,您可以在尝试再次读取之前执行其他操作。
猜你喜欢
  • 2012-02-18
  • 2013-03-23
  • 2013-08-20
  • 2017-10-23
  • 2016-11-29
  • 2015-10-27
  • 2012-01-14
  • 2015-11-26
  • 2012-08-27
相关资源
最近更新 更多