简体   繁体   English

带python套接字的端口,它们是随机的吗?

[英]Ports with python sockets, are they random?

I am trying to learn python sockets, but am becoming very confused by the results of the example code from the website ( found here ). 我正在尝试学习python套接字,但是对网站( 此处找到 )中示例代码的结果感到非常困惑。

The only modification I have made is replacing socket.gethostname() in the server with the local IP of my server, to allow me to run this on two computers. 我所做的唯一修改是用服务器的本地IP替换了服务器中的socket.gethostname() ,使我可以在两台计算机上运行它。

When I connect, attempting to connect on port 12345 as in the example, I get this output: 当我连接时,如示例中那样尝试在端口12345上进行连接,我得到以下输出:

Got connection from ('10.0.1.10', 37492)

This leads me to believe that it is connecting on port 37492. I would like it to connect on the port I tell it to, so I can port forward. 这使我相信它正在端口37492上进行连接。我希望它在我告诉它的端口上进行连接,因此我可以进行端口转发。 Am I misunderstanding, or is there an extra command to specify it. 我是误解了,还是有额外的命令来指定它。

Edit: I am uploading my code: 编辑:我正在上传我的代码:

Client.py 客户端

#!/usr/bin/python           # This is client.py file

import socket               # Import socket module

s = socket.socket()         # Create a socket object
host = socket.gethostname() # Get local machine name
port = 12345                # Reserve a port for your service.

s.connect(("10.0.1.42", port))
print s.recv(1024)
s.close                     # Close the socket when done

Server.py Server.py

import socket

s = socket.socket()         # Create a socket object
host = "10.0.1.42"          # Get local machine name
port = 12345                # Reserve a port for your service.
s.bind((host, port))        # Bind to the port

s.listen(5)                 # Now wait for client connection.
while True:
        c, addr = s.accept()     # Establish connection with client.
        print 'Got connection from', addr
        c.send('Thank you for connecting')
        c.close()                # Close the connection

You have reached that point in your networking life where you need to understand protocol multiplexing. 您已经达到网络生活中需要了解协议多路复用的程度。 Good for you. 对你有好处。

Think of the TCP/IP stack. 考虑一下TCP / IP堆栈。 An application communicates with a remote application by passing application-layer data to the transport (end-to-end) layer, which passes it to the network layer (internetwork layer) which tries, without guarantees, to have packets reach the IP destination host over a sequence of hops determined by cooperating routers that dynamically update their routing tables by talking to connected routers. 应用程序通过将应用程序层数据传递到传输(端到端)层,再将其传递到网络层(网络层),与应用程序进行远程通信,网络层(网络层)尝试不保证数据包到达IP目标主机由协作路由器确定的一系列跃点,这些路由器通过与连接的路由器进行通信来动态更新其路由表。 Each router conversation goes over a physical transport of some kind (ISDN, Ethernet, PPP - in TCP/IP the task of creating packets and transmitting the appropriate bit stream is regarded as a single "subnetwork" layer, but this is ultimately split into two when differentiation is required between the OSI physical layer (Layer 1) and the data link layer (layer 2) for protocols like DHCP. 每个路由器对话都经过某种物理传输(ISDN,以太网,PPP-在TCP / IP中创建数据包并传输适当的位流的任务被视为单个“子网”层,但最终将其分为两个层)当需要像DHCP这样的协议在OSI物理层(第1层)和数据链路层(第2层)之间进行区分时。

When TCP and UDP were designed, the designers imagined that each server would listen on a specific port. 在设计TCP和UDP时,设计人员想象每个服务器都将侦听特定端口。 This typically has the inherent limitation that the port can only handle one version of your service protocol (though protocols like HTTP take care to be backwards-compatible so that old servers/clients can generally interoperate with newer ones). 这通常具有固有的局限性,即该端口只能处理您的服务协议的一个版本(尽管像HTTP这样的协议会注意向后兼容,以便旧服务器/客户端通常可以与较新的服务器/客户端进行互操作)。 There is often a service called portmapper running on port 111 that allows servers to register the port number they are running on, and clients to query the registered servers by service (program) number and protocol version. 通常在端口111上运行一个名为portmapper的服务,该服务允许服务器注册它们在其上运行的端口号,而客户端可以通过服务(程序)号和协议版本查询注册的服务器。 This is a part of the Sun-designed RPC protocols, intended to expand the range of listening ports beyond just those that were pre-allocated by standards. 这是Sun设计的RPC协议的一部分,旨在将侦听端口的范围扩展到仅由标准预先分配的端口之外。 Since the preallocated ports were numbered from 1 to 1023, and since those ports typically (on a sensible operating system) require a high level of privilege, RPC also enabled non-privileged server processes as well as allowing a server to be responsive to multiple versions of network application protocols such as NFS. 由于预分配的端口号为1到1023,并且由于这些端口通常(在合理的操作系统上)需要高级别的特权,因此RPC还启用了非特权服务器进程,并允许服务器响应多个版本网络应用程序协议(例如NFS)。

However the server side works, the fact remains that there has to be some way for the network layer to decide which TCP connection (or UDP listener) to deliver a specific packet to. 无论服务器端如何工作,事实仍然是网络层必须有某种方法来决定将特定数据包传递到哪个TCP连接(或UDP侦听器)。 Similarly for the transport layer (I'll just consider TCP here since it's connection-oriented - UDP is similar, but doesn't mind losing packets). 对于传输层也是如此(我将在这里只考虑TCP,因为它是面向连接的-UDP类似,但不介意丢失数据包)。 Suppose I'm a server and I get two connections from two different client processes on the same machine. 假设我是服务器,并且我从同一台计算机上的两个不同客户端进程获得两个连接。 The destination (IP address, port number) will be the same if the clients are using the same version of the same protocol, or if the service only listens on a single port. 如果客户端使用的是同一协议的相同版本,或者服务仅在单个端口上侦听,则目的地(IP地址,端口号)将相同。

The server's network layer looks at the incoming IP datagram and sees that it's addressed to a specific server port. 服务器的网络层查看传入的IP数据报,并查看将其寻址到特定的服务器端口。 So it hands it off to that port in the transport layer (the layer above the network layer). 因此,它将其传递到传输层(网络层上方的层)中的该端口。 The server, being a popular destination, may have several connections from different different client processes on the same machine. 服务器是一个受欢迎的目的地,可能在同一台计算机上具有来自不同客户端进程的多个连接。 This is where the magic of ephemeral ports appears. 这就是短暂端口的神奇之处。

When the client requests a port to use to connect to a service, the TCP layer guarantees that no other process on that machine (technically, that interface, since different interfaces have unique IP addresses, but that's a detail) will be allocated the same port number while the client process continues to use it. 当客户端请求用于连接服务的端口时,TCP层保证该机器上的其他进程(从技术上来说,是该接口,因为不同的接口具有唯一的IP地址,但这很详细)不会分配给同一端口客户端进程继续使用它时编号。

So protocol multiplexing and demultiplexing relies on five pieces of information: 因此,协议复用和解复用依赖于五项信息:

(sender IP, sender port, protocol, receiver IP, receiver port) (发送方IP,发送方端口,协议,接收方IP,接收方端口)

The protocol is a field in the IP header as are the source and destination IP addresses. 协议是IP标头中的一个字段,源IP地址和目标IP地址也是如此。 The sending and receiving port numbers are in the transport layer segment header. 发送和接收端口号在传输层段头中。

When an incoming packet arrives, the guaranteed uniqueness of different ephemeral ports from the same client (endpoint) allows the transport layer to differentiate between different connections to the same server IP address from the same client IP address and port (the worst case for demultiplexing) by their source IP address and port. 当传入的数据包到达时,来自同一客户端(端点)的不同临时端口的保证唯一性允许传输层区分来自同一客户端IP地址和端口的到同一服务器IP地址的不同连接(最坏的情况是多路分解)通过其源IP地址和端口。 The (transport) protocol is included to ensure that TCP and UDP traffic don't get mixed up. 包含(传输)协议以确保TCP和UDP流量不会混淆。 The TCP/UDP constraints on uniqueness of ephemeral ports guarantee that any server can only receive one connection from a specific combination of (IP address, port number) and it's that that allows connections from the same machine to be demultiplexed into separate streams corresponding to the different origins. TCP / UDP对临时端口的唯一性的限制保证了任何服务器只能从(IP address, port number)的特定组合接收一个连接,并且该操作允许将来自同一台计算机的连接多路分解为与不同的起源。

In Python when you connect a socket to a remote endpoint the socket.accept() call returns the (IP address, port number) pair for the remote endpoint. 在Python中,当您将套接字连接到远程端点时, socket.accept()调用返回远程端点的(IP地址,端口号)对。 You can use that to discover who is communicating with you, but if you just want to talk back you can simply write() the socket. 您可以使用它来发现与您进行通讯的人,但是如果您只想讲回话,您可以简单地write()套接字。

The key word is "from." 关键字是“来自”。 That's the port that the client is connecting from, 12345 is the one your server is listening on and the client is connecting to. 这是客户端连接的端口,12345是服务器正在侦听且客户端连接的端口。

The port that you get in your output is the source port. 您在输出中获得的端口是源端口。 Your client program sends to the server on the port you choose (in this case, 12345), but it also needs a port to receive data sent by the server, so it randomly chooses a source port and tells it to the server. 您的客户端程序通过您选择的端口(在本例中为12345)发送到服务器,但是它也需要一个端口来接收服务器发送的数据,因此它会随机选择一个源端口并将其告知服务器。

I suggest you read some more about TCP and ports in general . 我建议您总体上阅读有关TCP端口的更多信息。

The message that appears comes from the server. 出现的消息来自服务器。 It just gives you information that connection was established from the client's port 37492. 它仅向您提供从客户端端口37492建立连接的信息。

This is what happens: 这是发生了什么:
Your server (server.py) is listening on port 12345. Your client (client.py) connects to the port 12345 of the server. 您的服务器(server.py)正在侦听端口12345。您的客户端(client.py)连接到服务器的端口12345。 The TCP connection is always established between two ports - source and destination. TCP连接始终在两个端口(源端口和目标端口)之间建立。 So, looking from your client app perspective 12345 is the destination port and 37492 is the source port. 因此,从客户端应用程序的角度来看,12345是目标端口,37492是源端口。 In other words client establishes a connection from its local port 37492 to the remote servers port 12345. 换句话说,客户端建立从其本地端口37492到远程服务器端口12345的连接。

If you want to set up port forwarding you may still do it as the port on which server listens is well known (12345) and the source port of the client doesn't really matter in this situation. 如果要设置端口转发,则仍然可以这样做,因为服务器侦听的端口是众所周知的(12345),在这种情况下客户端的源端口并不重要。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM