实现tcp的accept()函数

3 投票
1 回答
517 浏览
提问于 2025-04-18 10:36

作为学校作业的一部分,我们需要用 python 实现一个非常简单的 tcp 版本。通信是通过 udp 套接字来进行的。

我现在遇到的问题是关于 accept() 的实现,主要是如何支持多个客户端。我读了很多资料,但找不到能解答我问题的来源。以下是我现在的代码:

# Accepts an incoming connection. This method blocks until an incoming SYN message
# arrives, handles the SYN message and returns the socket.
def accept(self):
    if self.state < STCP_STATE_LISTEN:
        raise StcpSocketException("Socket not listening")

    # Extract syn segment
    while True:
        syn = stcp_packet.read_from_socket(self.sock)
        if syn.syn:
            log.debug("(%s,%s) received SYN %s" % (self.local_addr, self.local_port, syn))
            break

    # TODO allocates the TCP buffers and variables

    # Allocate new socket
    connection = stcp_socket()
    connection.bind(self.local_addr, 0)
    connection.remote_addr = syn.srcIp
    connection.remote_port = syn.srcPort
    connection.change_state(STCP_STATE_SYN_RCVD)

    # Send syn ack segment
    syn_ack = connection.create_empty_pkt(True, True, False, None, syn.seqNum + 1)
    self.seqNum += 1
    connection.sock.sendto(syn_ack.pack(), syn.srcIp, syn.srcPort)
    log.debug("(%s,%s) sent SYN ACK %s" % (connection.local_addr, connection.local_port, syn_ack))

    # Extract last segment in handshake process
    while True:
        ack = stcp_packet.read_from_socket(connection.sock)
        if ack.ack:
            log.debug("(%s,%s) received ACK %s" % (connection.local_addr, connection.local_port, ack))
            connection.change_state(STCP_STATE_ESTAB)
            break

    return connection

我的问题是:

  1. 新的套接字应该响应 syn 数据包,还是应该由旧的(监听)套接字来完成三次握手?
  2. 客户端应该继续向监听套接字发送数据包,然后监听套接字再把这些数据包转发给新创建的套接字,还是客户端应该从 syn_ack 数据包中获取新套接字的 IP 和端口,直接发送数据包给新套接字?

1 个回答

0

新的套接字应该回应syn包吗,还是让旧的(监听)套接字完成三次握手?

如果旧的套接字已经完成握手,那就应该由它来处理。对方应该期待整个握手过程都是从同一个IP和端口发来的。

客户端应该继续向监听套接字发送数据包,然后再由它转发给新创建的套接字吗?

不应该。

还是说客户端应该从syn_ack包中获取新套接字的IP和端口,然后直接发送数据包?

是的。最后的确认包需要包含新的端口号。

撰写回答