两台计算机之间使用Python套接字进行通信

20
我正在使用这两个程序在我的两台电脑之间进行通信,其中一台我通过ssh连接,但双方都没有返回任何东西。它只是运行而没有发送任何内容。
客户端
import sys
from socket import socket, AF_INET, SOCK_DGRAM

SERVER_IP   = '127.0.0.1'
PORT_NUMBER = 5000
SIZE = 1024
print ("Test client sending packets to IP {0}, via port {1}\n".format(SERVER_IP, PORT_NUMBER))

mySocket = socket( AF_INET, SOCK_DGRAM )

while True:
        mySocket.sendto('cool',(SERVER_IP,PORT_NUMBER))
sys.exit()

服务器

from socket import socket, gethostbyname, AF_INET, SOCK_DGRAM
import sys
PORT_NUMBER = 5000
SIZE = 1024

hostName = gethostbyname( '0.0.0.0' )

mySocket = socket( AF_INET, SOCK_DGRAM )
mySocket.bind( (hostName, PORT_NUMBER) )

print ("Test server listening on port {0}\n".format(PORT_NUMBER))

while True:
        (data,addr) = mySocket.recvfrom(SIZE)
        print data
sys.ext()

我可能做错了什么?

5个回答

21

问题出在您的客户端地址上:

SERVER_IP   = '127.0.0.1'

当你在连接本地机器并发送数据时,你的服务器位于不同的IP上。你需要连接到服务器的IP或主机名。

你可以通过先让客户端连接(如果无法连接则失败)来验证这一点。

...

import time

mySocket = socket( AF_INET, SOCK_DGRAM )
mySocket.connect((SERVER_IP,PORT_NUMBER))

while True:
        mySocket.send(b'cool')
        time.sleep(.5)

注明更新

因为你在一个wifi连接上,这意味着这两台机器都在同一个局域网内。您需要找到服务器的局域网IP地址,将其指定为目标。

使用命令行查找您的IP地址

  • OSX / Linux: ifconfig
  • Windows: ipconfig /all

我使用了whatismyip.com上的地址,结果是相同的。 - GreatGather
1
@user1340048:那是你的公共IP地址。除非你已经设置了路由器将端口上的流量转发到服务器机器,否则这对你没有什么用处。使用本地网络IP地址。这两台机器是否在两个不同的网络位置? - jdi
那么你确实希望使用本地网络IP。这取决于你的操作系统。查看你的网络配置以找到你的IP地址。通常在控制面板或命令行工具中。 - jdi
@user1340048:另外,将 SERVER_IP="" 设置为空与设置为 localhost 是相同的。由于它们运行在两台不同的机器上,你需要指定目标 IP。在 OSX/Linux 上可以使用命令:ifconfig en0。在 Windows 上可能是 ipconfig /all - jdi
有趣的是,当我运行这段代码时,它会报出一个 TypeError: a bytes-like object is required, not 'str' 的错误。我错过了什么?我正在运行 Python 3.9.7 版本。 - Strelok
显示剩余2条评论

14

这个程序用于从客户端发送“小写字母字符串”,并从服务器获取“大写字母”

服务器端

import socket

def Main():
   
    host = '192.168.0.12' #Server ip
    port = 4000

    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    s.bind((host, port))

    print("Server Started")
    while True:
        data, addr = s.recvfrom(1024)
        data = data.decode('utf-8')
        print("Message from: " + str(addr))
        print("From connected user: " + data)
        data = data.upper()
        print("Sending: " + data)
        s.sendto(data.encode('utf-8'), addr)
    c.close()

if __name__=='__main__':
    Main()

客户端

import socket

def Main():

    host='192.168.0.13' #client ip
    port = 4005
    
    server = ('192.168.0.12', 4000)
    
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    s.bind((host,port))
    
    message = input("-> ")
    while message !='q':
        s.sendto(message.encode('utf-8'), server)
        data, addr = s.recvfrom(1024)
        data = data.decode('utf-8')
        print("Received from server: " + data)
        message = input("-> ")
    s.close()

if __name__=='__main__':
    Main()

1
你应该能看到像这样的局域网IP地址:192.168.1.102,这是通常WiFi路由器默认的本地地址。例如,你可以通过使用ipconfig在Windows命令提示符中看到以下内容:
C:\Users\jackc>ipconfig

Windows IP Configuration

Wireless LAN adapter Wireless Network Connection 3:

   Media State . . . . . . . . . . . : Media disconnected
   Connection-specific DNS Suffix  . :

Wireless LAN adapter Wireless Network Connection:

   Connection-specific DNS Suffix  . :
   Link-local IPv6 Address . . . . . : fe80::ed97:91a4:9449:204b%13
   IPv4 Address. . . . . . . . . . . : 192.168.8.106
   Subnet Mask . . . . . . . . . . . : 255.255.255.0
   Default Gateway . . . . . . . . . : 192.168.8.1

我尝试了下面的测试代码,它对我有效。
客户端:
#!/usr/bin/env python3

import sys
from socket import socket, AF_INET, SOCK_DGRAM

SERVER_IP   = '192.168.8.102'
PORT_NUMBER = 5000
SIZE = 1024
print ("Test client sending packets to IP {0}, via port {1}\n".format(SERVER_IP, PORT_NUMBER))

mySocket = socket( AF_INET, SOCK_DGRAM )
myMessage = "Hello!"
myMessage1 = ""
i = 0
while i < 10:
    mySocket.sendto(myMessage.encode('utf-8'),(SERVER_IP,PORT_NUMBER))
    i = i + 1

mySocket.sendto(myMessage1.encode('utf-8'),(SERVER_IP,PORT_NUMBER))

sys.exit()

服务器:

#!/usr/bin/env python3

from socket import socket, gethostbyname, AF_INET, SOCK_DGRAM
import sys
PORT_NUMBER = 5000
SIZE = 1024

hostName = gethostbyname( '0.0.0.0' )

mySocket = socket( AF_INET, SOCK_DGRAM )
mySocket.bind( (hostName, PORT_NUMBER) )

print ("Test server listening on port {0}\n".format(PORT_NUMBER))

while True:
    (data,addr) = mySocket.recvfrom(SIZE)
    print data
sys.exit()

0

要连接到任意客户端,您必须将套接字绑定到socket.gethostname()(这是我正在成功使用的方法)或使用空字符串""

关于服务器代码:我们使用了socket.gethostname(),以便套接字对外界可见。如果我们使用了

s.bind(('localhost', 80)) 

或者

s.bind(('127.0.0.1', 80)) 

我们仍然会有一个“服务器”套接字,但它只在同一台机器内可见。s.bind(('',80))指定该套接字可由机器拥有的任何地址访问。

source


0
如果在将SERVER_IP更改为实际服务器地址后仍无法正常工作,请检查服务器防火墙是否接受端口5000上的UDP流量。
如果您的服务器是Linux机器,则iptables -L将显示防火墙规则。 iptables -F将删除所有(!)防火墙规则,因此您可以测试是否有所帮助。这不是重启持久性的。

很不幸,它还是无法工作,防火墙显示已允许所有内容。 - GreatGather

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接