我正在使用套接字制作一个聊天应用程序,但遇到了一个小问题。我在笔记本电脑上运行服务器,然后从同一笔记本电脑上的虚拟机内运行的客户端连接到服务器。
chat_server.py
import socket
import subprocess
import platform
from _thread import *
def get_local_ip():
system_platform = platform.system().lower()
try:
if system_platform == 'darwin':
# macOS
result = subprocess.run(["ifconfig", "en0"], capture_output=True, text=True, check=True)
local_ip = [line.split()[1] for line in result.stdout.splitlines() if "inet " in line][0]
elif system_platform == 'linux':
# Linux
result = subprocess.run(["ifconfig"], capture_output=True, text=True, check=True)
# Find the first non-loopback IPv4 address
local_ip = next((line.split()[1] for line in result.stdout.splitlines() if "inet " in line and "127.0.0.1" not in line), None)
elif system_platform == 'windows':
# Windows
result = subprocess.run(["ipconfig"], capture_output=True, text=True, check=True)
local_ip = [line.split(":")[1].strip() for line in result.stdout.splitlines() if "IPv4 Address" in line][0]
else:
print("Unsupported operating system")
return None
if local_ip is None:
raise Exception("Failed to retrieve a valid local IP address.")
return local_ip
except subprocess.CalledProcessError as e:
print(f"Error running command: {e}")
return None
except Exception as e:
print(f"Error getting local IP: {e}")
return None
def start_server():
host_ip = get_local_ip()
port_number = int(input("Enter the port number: "))
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind((host_ip, port_number))
server_socket.listen(100)
print(f"{host_ip} listening on port {port_number}")
client_list = []
def handle_client(client_conn, client_address):
client_conn.send("Connection successful. You can now start chatting!".encode('utf-8'))
while True:
try:
message = client_conn.recv(2048)
if message:
print(f"{client_address[0]}: {message.decode('utf-8')}")
broadcast_message = f"{message.decode('utf-8')}"
broadcast(broadcast_message, client_conn)
else:
remove_client(client_conn)
except:
continue
def broadcast(message, sender_connection):
for client_socket in client_list:
if client_socket != sender_connection:
try:
client_socket.send(message.encode('utf-8'))
except:
client_socket.close()
remove_client(client_socket)
def remove_client(client_connection):
if client_connection in client_list:
client_list.remove(client_connection)
while True:
client_conn, client_addr = server_socket.accept()
client_list.append(client_conn)
print(f"{client_addr[0]} connected")
start_new_thread(handle_client, (client_conn, client_addr))
client_conn.close()
server_socket.close()
if __name__ == "__main__":
start_server()
chat_client.py
import socket
import select
import sys
def start_client():
server_ip = input("Enter the server IP address: ")
server_port = int(input("Enter the server port: "))
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect((server_ip, server_port))
username = input("Enter your username: ")
while True:
active_sockets = [sys.stdin, client_socket]
readable_sockets, _, _ = select.select(active_sockets, [], [])
for current_socket in readable_sockets:
if current_socket == client_socket:
message = current_socket.recv(2048).decode('utf-8')
print(message)
else:
message = sys.stdin.readline()
client_socket.send(f"{username}: {message}".encode('utf-8'))
client_socket.close()
if __name__ == "__main__":
start_client()
每当客户端连接到服务器时,服务器应该显示已连接的客户端的IP,但它一直显示服务器的IP。
示例 输入端口号:5000 10.180.186.206 监听端口 5000 10.180.186.206 已连接
我在虚拟机上运行 ifconfig 来获取其 IP,就我而言,当客户端连接时服务器应该显示此信息:
输入端口号:5000 10.180.186.206 监听端口 5000 10.211.55.7 已连接
如何让显示已连接客户端的IP地址而不是服务器IP。
套接字由三部分组成:
IP地址 传输协议 端口号 端口是介于 1 和 65535 之间的数字,表示设备中的逻辑门。客户端和服务器之间的每个连接都需要一个唯一套接字。
例如:
1030 是端口。 (190.10.10.2,TCP,端口1530)是一个套接字。