Search code examples
c#pythonsocketsraspberry-pilan

Send/receive file over LAN with C# to/from Python


I'm pretty new to Python development and need some help.

I have a Raspberry Pi B+, and I'm planning on using it as a controller for household things (such as turning on a pool pump at a set time). I am pretty familiar with C# and was wondering if there was a way I could write a C# user interface to run on a laptop and send data in the form of a XML file to the Raspberry Pi over a LAN to tell the Pi what to do. I have written some code in C# and some code in Python to try to send and receive a file, but so far my tests have been unsuccessful.

I have some rudimentary code written in Python on the Raspberry Pi for controlling some GPIO pins and was wondering if a connection like this is even feasible of if I should rewrite my Python code into C# also.

Here is my C# send file function

public void SendFile(string fileName)
{
    try
    {
        string IpAddressString = piIP;
        IPEndPoint ipEnd_client = new IPEndPoint(IPAddress.Parse(IpAddressString), portnumber);
        Socket clientSock_client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);

        string filePath = "";

        fileName = fileName.Replace("\\", "/");
        Console.WriteLine(fileName);

        while (fileName.IndexOf("/") > -1)
        {
            filePath += fileName.Substring(0, fileName.IndexOf("/") + 1);
            fileName = fileName.Substring(fileName.IndexOf("/") + 1);
        }

        byte[] fileNameByte = Encoding.UTF8.GetBytes(fileName);
        if (fileNameByte.Length > 5000 * 1024)
        {
            Console.WriteLine("File size is more than 5Mb, please try with small file.");
            return;
        }

        Console.WriteLine("Buffering ...");
        string fullPath = filePath + fileName;

        byte[] fileData = File.ReadAllBytes(fullPath);
        byte[] clientData = new byte[4 + fileNameByte.Length + fileData.Length];
        byte[] fileNameLen = BitConverter.GetBytes(fileNameByte.Length);


        fileNameLen.CopyTo(clientData, 0);
        fileNameByte.CopyTo(clientData, 4);
        fileData.CopyTo(clientData, 4 + fileNameByte.Length);

        Console.WriteLine("Connection to server...");
        clientSock_client.Connect(ipEnd_client);

        Console.WriteLine("File sending...");
        clientSock_client.Send(clientData, 0, clientData.Length, 0);

        Console.WriteLine("Disconnecting...");
        clientSock_client.Close();
        Console.WriteLine("File [" + fullPath + "] transferred.");
    }
    catch (Exception ex)
    {
        if (ex.Message == "No connection could be made because the target machine actively refused it")
            Console.WriteLine("File Sending fail. Because server not running.");
        else
            Console.WriteLine("File Sending fail. " + ex.Message);
        return;
    }
    connected = true;
    return;
}

Here is my Python receive file function

import socket
import sys
s = socket.socket()
s.bind((socket.gethostname(), 8080))
s.listen(3)

while True:

    #Accept connections from the outside
    (clientsocket, address) = s.accept()
    print(address)
    i = 1
    f = open('file_' + str(i) + ".xml", 'wb')
    i = i + 1
    while True:
        l = clientsocket.recv(1024)
        while l:
            f.write(1)
            l.clientsocket.recv(1024)
    f.close()

    sc.close()

s.close()

Again, so far, I am unable to even set up a connection between the two devices. Should I start over on the Pi and try C# instead of Python? Or am I missing something? I've given both devices a static IP address and hardcoded the IP addresses on both machine for now.

EDIT: Here is the Console and stacktrace I get from C#:

Buffering ...
Connection to server...
A first chance exception of type 'System.Net.Sockets.SocketException' occurred in System.dll
File Sending fail. No connection could be made because the target machine actively refused it 10.51.21.199:8080
at System.Net.Sockets.Socket.DoConnect(EndPoint endPointSnapshot, SocketAddress socketAddress)
at System.Net.Sockets.Socket.Connect(EndPoint remoteEP)
at App1.Stuffs.SendFile(String fileName) in
...Projects\App1\App1\Stuffs.cs:line 308
The thread '<No Name>' (0x1684) has exited with code 0 (0x0).

Solution

  • Try to use

    s.bind(('', 8080))
    

    to force the Raspberry Pi to listen on all available interfaces, as the socket.gethostname() might not be the interface you are actually expecting.

    UPDATE:

    Try this on the Raspberry Pi side:

    import socket
    import sys
    s = socket.socket()
    s.bind(('', 8080))
    s.listen(3)
    
    i = 0
    
    while True:
    
        #Accept connections from the outside
        (clientsocket, address) = s.accept()
        print(address)
        i = i + 1
        with open('file_' + str(i) + ".xml", 'wb') as f:
            while True:
                l = clientsocket.recv(1024)
                if not l:
                    break
                f.write(l)
    
        clientsocket.close()
    
    s.close()