我正在尝试学习python套接字,但是我对网站上的示例代码(found here)的结果感到非常困惑。
我所做的唯一修改就是用我服务器的本地IP替换服务器中的socket.gethostname()
,以允许我在两台计算机上运行它。
当我连接时,尝试连接端口12345,如示例中所示,我得到此输出:
Got connection from ('10.0.1.10', 37492)
这让我相信它正在连接端口37492.我希望它连接到我告诉它的端口,所以我可以移植。我误解了,还是有额外的命令来指定它。
编辑:我正在上传我的代码:
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
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
答案 0 :(得分:2)
您已达到网络生活中的那一点,您需要了解协议多路复用。对你有好处。
想想TCP / IP堆栈。应用程序通过将应用程序层数据传递到传输(端到端)层与远程应用程序进行通信,传输(端到端)层将其传递到网络层(互联网络层),该网络层无需担保即可尝试使数据包到达IP目标主机通过协作路由器确定的一系列跳数,这些路由器通过与连接的路由器通信来动态更新其路由表。每个路由器会话通过某种物理传输(ISDN,以太网,PPP - 在TCP / IP中创建数据包和传输适当的比特流的任务被视为单个“子网”层,但这最终分为两个当OSI物理层(第1层)和数据链路层(第2层)之间需要区分DHCP协议时。
设计TCP和UDP时,设计人员想象每个服务器都会侦听特定端口。这通常具有固有的局限性,即端口只能处理一个版本的服务协议(尽管像HTTP这样的协议需要向后兼容,以便旧服务器/客户端通常可以与新的服务器/客户端进行互操作)。通常在端口111上运行一个名为portmapper的服务,允许服务器注册它们运行的端口号,客户端通过服务(程序)号和协议版本查询注册的服务器。这是Sun设计的RPC协议的一部分,旨在扩展侦听端口的范围,而不仅仅是那些预先由标准分配的端口。由于预分配的端口编号为1到1023,并且由于这些端口通常(在合理的操作系统上)需要高级别的权限,因此RPC还启用了非特权服务器进程以及允许服务器响应多个版本网络应用程序协议,如NFS。
然而,服务器端工作,事实仍然是网络层必须有某种方式来决定将特定数据包传递到哪个TCP连接(或UDP侦听器)。类似地,对于传输层(我在这里只考虑TCP,因为它是面向连接的 - UDP类似,但不介意丢失数据包)。假设我是一台服务器,我在同一台机器上从两个不同的客户端进程获得两个连接。如果客户端使用相同协议的相同版本,或者服务仅侦听单个端口,则目标(IP地址,端口号)将相同。
服务器的网络层查看传入的IP数据报,并发现它是发往特定服务器端口的。因此,它将其交给传输层中的端口(网络层上方的层)。作为流行目的地的服务器可以在同一台机器上具有来自不同不同客户端进程的多个连接。这就是短暂港口的神奇之处。
当客户端请求端口用于连接服务时,TCP层保证该机器上没有其他进程(从技术上讲,该接口,因为不同的接口具有唯一的IP地址,但是这是一个细节)将被分配相同的端口号,而客户端进程继续使用它。
协议多路复用和多路分解依赖于五条信息:
(发送方IP,发送方端口,协议,接收方IP,接收方端口)
协议是IP头中的字段,源IP地址和目标IP地址也是如此。发送和接收端口号位于传输层段头中。
当传入数据包到达时,来自同一客户端(端点)的不同短暂端口的保证唯一性允许传输层区分来自相同客户端IP的相同服务器IP地址的不同连接它们的源IP地址和端口的地址和端口(最坏情况下是多路分解)。包含(传输)协议以确保TCP和UDP流量不会混淆。短暂端口唯一性的TCP / UDP约束保证任何服务器只能从(IP address, port number)
的特定组合接收一个连接,并且允许来自同一台机器的连接被多路分解为对应于不同来源的单独流
在Python中,当您将套接字连接到远程端点时,socket.accept()
调用将返回远程端点的(IP地址,端口号)对。您可以使用它来发现与您通信的人,但如果您只是想要回话,您只需write()
套接字。
答案 1 :(得分:1)
关键词是“来自”。这是客户端连接的端口,12345是您的服务器正在侦听并且客户端正在连接的端口。
答案 2 :(得分:0)
您在输出中获得的端口是源端口。您的客户端程序在您选择的端口上发送到服务器(在本例中为12345),但它还需要一个端口来接收服务器发送的数据,因此它会随机选择一个源端口并将其告知服务器。
我建议您阅读有关TCP和ports in general的更多信息。
答案 3 :(得分:0)
出现的消息来自服务器。它只是为您提供从客户端的端口37492建立连接的信息。
这是发生的事情:
您的服务器(server.py)正在侦听端口12345.您的客户端(client.py)连接到服务器的端口12345。始终在两个端口(源和目标)之间建立TCP连接。
因此,从客户端应用程序角度看12345是目标端口,37492是源端口。换句话说,客户端建立从其本地端口37492到远程服务器端口12345的连接。
如果你想设置端口转发,你仍然可以将其作为服务器监听的端口众所周知(12345),并且在这种情况下客户端的源端口并不重要。