Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
python可靠的UDP和数据包“忽略”功能,带有select非阻塞_Python_Sockets_Udp - Fatal编程技术网

python可靠的UDP和数据包“忽略”功能,带有select非阻塞

python可靠的UDP和数据包“忽略”功能,带有select非阻塞,python,sockets,udp,Python,Sockets,Udp,我是python的新手,目前正在使用select的非阻塞调用处理客户端和服务器端脚本。这是为了在数据包丢失的情况下可靠地将文件从客户端发送到服务器。我不想使用Twisted或Eventlet等预先存在的模块 我假设没有数据包延迟,但只有随机丢弃发生。我将只在服务器端构建丢弃模拟函数,它将是“传入的数据包丢弃函数服务器以随机概率将数据保存到来自套接字的“虚拟”变量,因此套接字不可读,直到新数据包进来,进程才会停止”,和“传出ACK drop”功能,即使服务器接收到数据并将数据写入文件,ACK也不会

我是python的新手,目前正在使用select的非阻塞调用处理客户端和服务器端脚本。这是为了在数据包丢失的情况下可靠地将文件从客户端发送到服务器。我不想使用Twisted或Eventlet等预先存在的模块

我假设没有数据包延迟,但只有随机丢弃发生。我将只在服务器端构建丢弃模拟函数,它将是“传入的数据包丢弃函数服务器以随机概率将数据保存到来自套接字的“虚拟”变量,因此套接字不可读,直到新数据包进来,进程才会停止”,和“传出ACK drop”功能,即使服务器接收到数据并将数据写入文件,ACK也不会发送,或发送但客户端无法到达。我已经构建了第一个,但还没有ACK drop函数

直到现在,我可以在没有丢包的情况下发送文件。然而,当有数据包丢失时,我希望我的客户端等待几秒钟,并一次又一次地发送具有相同数据的数据包,直到它从服务器接收到之前发送的数据包的ACK。但当服务器模拟丢包时,客户端功能停止工作。我认为我的代码有问题,需要建议。除此之外,我很高兴听取关于编写此类代码的最佳实践的任何反馈。多谢各位

以下是我迄今为止所做的工作。对我糟糕的编码方式表示抱歉,顺便说一下:

客户端

import socket
import sys
import select
import time

host = ''
port = 1238
buf = 9216  # Jumboframe
addr = (host, port)
p_cnt = 0
read_cnt = 0
response_cnt = 0
response = ('','')
data = ''


# Socket Creation, binding
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(('', 9996))

# Receive file name from user
file_name = "lol.png" # raw_input("Enter the name of the file: ")
f = open(file_name, "rb")
readable = [s, f]
writable = [s]
prev_data = file_name

while s:
    try:
        rd, wt, er = select.select(readable, writable, [], 0)

        # When readable
        for rsk in rd:
            if rsk is s:  # When socket is readable (3. Receive ACK from packet)
                if p_cnt > response_cnt:  # If sent packets > received response
                    response = s.recvfrom(buf)  # Receive response from server
                    response_cnt += 1  # Increase the response counter by 1
                    print response[0]  # Printout the received response

            else:  # When socket is not readable
                if read_cnt > response_cnt: # When there is any data that has been read from file but not sent yet
                    start_time = time.time() # Start checking time
                    while 1:
                        if time.time() - start_time == 3:  # When 3 second has been passed since the start time
                            print "Seems packet has been dropped, resending " + str(p_cnt) + " packet"
                            #for wsk in wt:
                            #    if wsk is s:
                            s.sendto(data, addr)  # Send the packet again
                            break  # And break

        # When readable
        for rsk in rd:
            if rsk is f:  # When file is readable (2. Read data from FILE)
                if response_cnt > read_cnt:  # If received response > file read
                    data = f.read(buf)  # Read more file
                    read_cnt += 1  # And Increase the read counter by 1
                    if data:  # If there is a data read from file in buffer,
                        # print how many times it read the file
                        #if p_cnt > response_cnt:
                        #    prev_data = data
                        print "Reading file...(" + str(read_cnt) + ")"
                    else:  # If there is no data in the buffer,
                        # print there is no more data to send and close fileIO
                        print "No more data"

        # When writable
        for wsk in wt:
            if wsk is s:  # If socket is writable (1. Send data to server)
                # If there is no packet sent to the server before
                if p_cnt == 0:
                    # This is the sending the first packet includes file name
                    print "Sending file name"
                    # Send the file name to the server
                    s.sendto(file_name, addr)
                    # Print we sent the file name to server
                    print "File name sent"
                    p_cnt += 1  # And increase sent packet counter by 1
                else:  # If it's not a first packet to send
                    # If reading counter is same as packet counter,
                    # which mean we received response for what we sent
                    if read_cnt == p_cnt:
                        # If there is a data to send to server in the buffer
                        if(data):
                            # Send that data to the server
                            s.sendto(data, addr)
                            # And print out we just sent the data
                            print "Sent " + str(p_cnt) + " packet"
                            # And increase the sent packet counter by 1
                            p_cnt += 1
                        else:  # If there is no data to send
                            # Sending empty data to let server know EOF
                            print "Sending EOF"
                            s.sendto("EOF", addr)
                            #s.sendto(data, addr)
                            p_cnt += 1

        if response[0] == "ACK EOF":
            print "Transmission complete"  # Print the status
            break

    except socket.error, msg:
        print 'Error Code : ' + str(msg[0]) + ' - ' + msg[1]
        sys.exit()

f.close()
s.close()  # Close the socket
sys.exit()
服务器端

import socket
import sys
import select
import random

host = ''
port = 1238
buf = 9216 # Jumboframe
p_cnt = 0
response_cnt = 0
write_cnt = 0
dummy = ''

p1 = 0.8  # Probability that the packet will be dropped

# Socket creation, binding
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind((host, port))

# Start waiting for the socket
print "Waiting for incoming"
data, addr = s.recvfrom(buf)  # Blocking

# Received first packet that contains file name
print "Received File: ", data.strip()
p_cnt += 1
file_name = data.strip()
f = open(file_name, "wb")

readable = [s]
writable = [s, f]

while s:
    try:
        rd, wt, er = select.select(readable, writable, [], 0)
        response = "ACK " + str(p_cnt)

        # When readable
        for rsk in rd:
            if rsk is s:  # When socket is readable (1. Receive data)
                # If there's only one packet received and no file written
                if p_cnt == 1 and write_cnt == 0:
##############################################################################
                    if int(random.random() >= p1) == 1:
                        # Incoming packet dropped - Make socket unreadable
                        dummy, addr = s.recvfrom(buf)
                        print "Incoming packet " + str(p_cnt+1) + " dropped"
##############################################################################
                    else:
                        # Read the received data from socket
                        data, addr = s.recvfrom(buf)
                        # Print how many packet has been received until now
                        print "Received " + str(p_cnt) + " packet"
                # If it's not the first packet or data has been written before
                else:  # If the number of received packet = number of sent ACK
                    # responsed to all the received packets to the client
                    if p_cnt == response_cnt:
##############################################################################
                        if int(random.random() >= p1) == 1:
                        # Incoming packet dropped - Make socket unreadable
                            dummy, addr = s.recvfrom(buf)
                            print "Incoming packet " + str(p_cnt+1) + " dropped"
##############################################################################
                        else:
                            # Read more data from socket and save to buffer
                            data, addr = s.recvfrom(buf)
                            # And increase the received packet counter by 1
                            p_cnt += 1
                            if data:  # If there is data to read from socket,
                                # Print out how many packet that we have received
                                print "Received " + str(p_cnt) + " packet"
                            else:  # If there is no data to read from socket,
                                # Print out there is no more data to read
                                print "No more data, closing file"

        # When writable
        for wsk in wt:
            # When socket is writable (3. Send ACK)
            if wsk is s:
                # If number of writing times > number of ACK sent
                if write_cnt > response_cnt:
                    # Send ACK to client
                    s.sendto(response, addr)
                    # And increase number of ACK sent
                    response_cnt += 1

            # When file is writable (2. Write on FILE)
            if wsk is f:
                # If number of packet received > number of file writing
                if p_cnt > write_cnt:
                    # If there is data to write in the buffer
                    if data and data != "EOF":
                        # And if it's not the first packet(file name, which shouldn't be written in file)
                        if p_cnt != 1:
                            f.write(data) # Write buffer to the file
                        write_cnt += 1 # And increase write counter
                        # Print how many times the buffer has been writted
                        print "Wrote " + str(p_cnt) + " packet"
                    else: # If there is no data to write in the buffer
                        print "Sending ACK EOF"
                        s.sendto("ACK EOF", addr)

        if data == "EOF":
            print "File Downloaded"  # Print out the file download completed
            break

    except socket.error, msg:
        print 'Error Code : ' + str(msg[0]) + ' - ' + msg[1]
        sys.exit()

f.close()
s.close()  # Close the socket
sys.exit()
客户热线

            else:  # When socket is not readable
是错误的-如果rsk是s,则else属于,因此在rsk是f,i的条件下达到。E当文件可读时

然后,下一行

                if read_cnt > response_cnt: # When there is any data that has been read from file but not sent yet
是错误的-read_cnt最多等于,但决不大于response_cnt,因为

            if response_cnt > read_cnt:  # If received response > file read
                data = f.read(buf)  # Read more file
                read_cnt += 1  # And Increase the read counter by 1
增量读取


我建议从readable中删除f,并在必要时假设文件是可读的,以及从writable中删除s,同时在while s:loop之前移动文件名包的发送,删除繁忙的等待,并在select调用中使用超时3;然后,当到达超时时,您可以再次发送数据包。

这是为了在数据包丢失的情况下可靠地将文件从客户端发送到服务器,这不是TCP的目的吗?是的,但我想开发一个非常简单的带UDP的拖放重发模型,以便在将来增强实现。