与Python的C#通信无法建立连接,因为目标计算机主动拒绝了它

2024-09-29 19:29:33 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图通过TCP/IP连接建立通信,但在将C#client连接到Python服务器时遇到问题。 它抛出一个SocketException

System.Net.Sockets.SocketException: No connection could be made because the target machine actively refused it

我很确定它发生在它试图连接到Python服务器的那一行:sender.Connect(remoteEP);

我试过的

  • 在我使用IPv4协议和Pythons socket.AF_INET之前,我发现我在C#中对IP地址的解析似乎使其成为IPv6地址,所以我现在使用的是IPv6地址,但这并没有解决问题
  • 我还尝试使用IPAddress.Parse(ip)而不是首先使用Dns.GetHostEntry(ip)获取主机,但这似乎没有起到任何作用

代码

C#代码:

using UnityEngine;
using System;
using System.Net;
using System.Net.Sockets;
using System.Collections;
using System.Text;


public class PyCommunicator : MonoBehaviour {

    private string ip = "::1"; // Localhost
    private int port = 14654;
    public string dataStringToSend
    {
        get { return dataStringToSend; }
        set { dataStringToSend = value; }
    }

    private void Start()
    {
        StartCoroutine(RequestServerCoroutine());
    }

    IEnumerator RequestServerCoroutine()
    {
        while (true)
        {
            RequestServer();
            yield return new WaitForSecondsRealtime(10);
        }
    }

    public void RequestServer()
    {
        byte[] bytes = new byte[1024]; // 1 KiloByte
        try
        {
            // Connect to a Remote server,
            // and get host IP Address that is used to establish a connection.
            // In this case, we get one IP address of localhost that is IPv6 : ::1 
            // If a host has multiple addresses, you will get a list of addresses  
            IPHostEntry host = Dns.GetHostEntry(ip);
            IPAddress ipAddress = host.AddressList[0];
            IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);

            // Create a TCP/IP  socket.    
            Socket sender = new Socket(AddressFamily.InterNetworkV6,
                SocketType.Stream, ProtocolType.Tcp);

            // Connect the socket to the remote endpoint. Catch any errors.    
            try
            {
                // Connect to Remote EndPoint  
                sender.Connect(remoteEP);

                Debug.Log("Successfully established a connection between Unity and Python.");

                // Encode the data string into a byte array.
                dataStringToSend = "Test from C#";
                if (dataStringToSend != "")
                {
                    byte[] msg = Encoding.ASCII.GetBytes(dataStringToSend);
                    // Send the data through the socket.
                    int bytesSent = sender.Send(msg);
                    // Reset.
                    dataStringToSend = "";
                }

                // Receive the response from the remote device.    
                int bytesRec = sender.Receive(bytes);
                Debug.LogFormat("Echoed test = {0}",
                    Encoding.ASCII.GetString(bytes, 0, bytesRec));

                // Release the socket.    
                sender.Shutdown(SocketShutdown.Both);
                sender.Close();

            }
            catch (ArgumentNullException ane)
            {
                Debug.LogFormat("ArgumentNullException: {0}", ane.ToString());
            }
            catch (SocketException se)
            {
                Debug.LogFormat("SocketException: {0}", se.ToString());
            }
            catch (Exception e)
            {
                Debug.LogFormat("Unexpected exception: {0}", e.ToString());
            }

        }
        catch (Exception e)
        {
            Debug.LogFormat("Exception from setup: {0}", e.ToString());
        }
    }
}

C#代码取自客户机部分的this链接,并进行了修改以供我自己使用

Python代码:

import socket
from time import sleep


class Communicator():

    def __init__(self, ip, port):
        self.ip = ip
        self.port = port

        self.data_to_send = None
        self.socket = None
        self.socket_conn = None
        self.socket_addr = None

        # Start listening right away.
        self.start()

    
    def start(self):
        """Start listening and accept connection."""
        self.socket = socket.socket(socket.AF_INET6,  socket.SOCK_STREAM)
        self.socket.bind((self.ip, self.port))

        # Begin listening for 1 connection.
        self.socket.listen(1)
        print("Socket is listening on ip (" + str(self.ip) + ") and port " + str(self.port))
        self.socket_conn, self.socket_addr = self.socket.accept()
        print("Connection between Unity and Python established. Unity-C# is at: " + str(self.socket_addr))
        
        sleep(5) # TESTING PURPOSES

        # Receive.
        result = ""
        chunk_counter = 0
        while True:
            # Allow the server to read up to 1024 bytes.
            data = self.conn.recv(1024)
            chunk_counter += 1
            # To minimize lag, read guess in chunks.
            if chunk_counter < 5:
                result += data.decode()
            
            # If reading the guess is done,
            # break out of loop.
            if not data:
                break
        
        # Send.
        self.socket.send("Test from python".encode())

        # Close
        self.socket.close()


    def send_data(self):
        """Send data"""
        pass


    def receive_data(self):
        """Receive data"""
        pass


Communicator('::1', 14654)

Tags: andthetodebugselfipdataport
1条回答
网友
1楼 · 发布于 2024-09-29 19:29:33

看来我在StackOverflow论坛上搜索得不够。 我在this中给出的代码和答案中找到了一个解决方案

我不需要使用实际的localhost环回地址,而是需要通过C#的DNS函数获取HOSTNAME地址:

Dns.GetHostName()

我还在Python中使用了socket.gethostname(),这样它们在连接时就有了相同的地址

我还将整个过程更改为使用IPv4地址,并在链接问题的答案中发现host.AddressList中的第一个元素包含IPv6地址,而第二个也是最后一个元素包含IPv4地址,这是缺少的部分

更新代码

C#代码:

using UnityEngine;
using System;
using System.Net;
using System.Net.Sockets;
using System.Collections;
using System.Text;


public class PyCommunicator : MonoBehaviour {

    private int port = 14654;
    public string dataStringToSend
    {                                                                               
        get { return dataStringToSend; }
        set { dataStringToSend = value; }
    }

    private void Start()
    {
        StartCoroutine(RequestServerCoroutine());
    }

    IEnumerator RequestServerCoroutine()
    {
        while (true)
        {
            RequestServer();
            yield return new WaitForSecondsRealtime(10);
        }
    }

    public void RequestServer()
    {
        byte[] bytes = new byte[1024]; // 1 KiloByte
        try
        {
            // Connect to a Remote server,
            // and get host IP Address that is used to establish a connection.
            // In this case, we get one IP address of localhost that is IP : 127.0.0.1
            // If a host has multiple addresses, you will get a list of addresses  
            IPHostEntry host = Dns.GetHostEntry(Dns.GetHostName());
            IPAddress ipAddress = host.AddressList[1];
            IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);

            // Create a TCP/IP  socket.    
            Socket sender = new Socket(ipAddress.AddressFamily,
                SocketType.Stream, ProtocolType.Tcp);

            // Connect the socket to the remote endpoint. Catch any errors.    
            try
            {
                // Connect to Remote EndPoint  
                sender.Connect(remoteEP);

                Debug.Log("Successfully established a connection between Unity and Python.");

                // Encode the data string into a byte array.
                dataStringToSend = "Test from C#";
                if (dataStringToSend != "")
                {
                    byte[] msg = Encoding.ASCII.GetBytes(dataStringToSend);
                    // Send the data through the socket.
                    int bytesSent = sender.Send(msg);
                    // Reset.
                    dataStringToSend = "";
                }

                // Receive the response from the remote device.    
                int bytesRec = sender.Receive(bytes);
                Debug.LogFormat("Echoed test = {0}",
                    Encoding.ASCII.GetString(bytes, 0, bytesRec));

                // Release the socket.    
                sender.Shutdown(SocketShutdown.Both);
                sender.Close();

            }
            catch (ArgumentNullException ane)
            {
                Debug.LogFormat("ArgumentNullException: {0}", ane.ToString());
            }
            catch (SocketException se)
            {
                Debug.LogFormat("SocketException: {0}", se.ToString());
            }
            catch (Exception e)
            {
                Debug.LogFormat("Unexpected exception: {0}", e.ToString());
            }

        }
        catch (Exception e)
        {
            Debug.LogFormat("Exception from setup: {0}", e.ToString());
        }
    }
}

Python代码:

import socket
from time import sleep


class Communicator():

    def __init__(self, ip, port):
        self.ip = ip
        self.port = port

        self.data_to_send = None
        self.socket = None
        self.socket_conn = None
        self.socket_addr = None

        # Start listening right away.
        self.start()

    
    def start(self):
        """Start listening and accept connection."""
        self.socket = socket.socket(socket.AF_INET,  socket.SOCK_STREAM)
        self.socket.bind((self.ip, self.port))

        # Begin listening for 1 connection.
        self.socket.listen(1)
        print("Socket is listening on ip (" + str(self.ip) + ") and port " + str(self.port))
        self.socket_conn, self.socket_addr = self.socket.accept()
        print("Connection between Unity and Python established. Unity-C# is at: " + str(self.socket_addr))
        
        sleep(5) # TESTING PURPOSES

        # Receive.
        result = ""
        chunk_counter = 0
        while True:
            # Allow the server to read up to 1024 bytes.
            data = self.conn.recv(1024)
            chunk_counter += 1
            # To minimize lag, read guess in chunks.
            if chunk_counter < 5:
                result += data.decode()
            
            # If reading the guess is done,
            # break out of loop.
            if not data:
                break
        
        # Send.
        self.socket.send("Test from python".encode())

        # Close
        self.socket.close()


    def send_data(self):
        """Send data"""
        pass


    def receive_data(self):
        """Receive data"""
        pass


Communicator(socket.gethostname(), 14654)

相关问题 更多 >

    热门问题