user2117118
user2117118

Reputation: 73

C# send integer to python

I am trying to send two integers to a python client script (which is running on a Linux machine) from a C# program (the server) which is running on a pc, using socket technology. Until now I am able to send strings.

Server:

TcpListener listener = new TcpListener(IPAddress.Any, 12345);
Invoke(new PrintMsg(printMsg), new object[] { "Trying to connect" });
listener.Start();

for(; ; ;)
{
   TcpClient client = null;

   try
   {
      client = listener.AcceptTcpClient();
      netStream = client.GetStream();
      Invoke(new PrintMsg(printMsg), new object[] { "Found client" });


      //send command to client
      ASCIIEncoding encoder = new ASCIIEncoding();
      byte[] buffer = encoder.GetBytes("Hello client");
      netStream.Write(buffer, 0, buffer.Length);
      netStream.Flush();

   }

   catch (Exception ex)
   {
      Invoke(new PrintMsg(printMsg), new object[] { ex.ToString() });
   }
}

And the client code is:

while True:
    msg = s.recv(1024)
    print 'SERVER:', msg

So I would like to "put" into a buffer array an integer and then send it to the python script. Is it possible? What am I doing wrong?

Upvotes: 0

Views: 1194

Answers (2)

abarnert
abarnert

Reputation: 365925

Before you can get to the problem of "how do I send an integer?", you need to solve a bigger problem: "how do I send a message?"

In TCP, when you call send on one side, even if it sends the whole buffer at once (which isn't guaranteed), the other side may get the data in multiple separate recv calls rather than all at once. Worse, it may get part of one send and part of the next send in a single recv.

You can use a higher-level protocol—like ZeroMQ, or even HTTP—that takes care of this for you. But if you just want to use raw TCP, you have to handle it yourself.

One obvious solution is a delimiter like newlines (or NUL bytes, etc.)—but then of course you need some way of escaping newlines in the middle of messages. Another possibility is to use some kind of header that describes the rest of the message, like netstring. Or you can use a self-delimiting message type like JSON.

Many really simple ways of handling the delimiter problem automatically take care of sending integers. JSON includes numbers as a type. Or you can just send the integers as strings over netstrings or newline-separated strings.

If you really want to encode the numbers in some "binary" way, you have to pick a representation, and write the code to convert to and from that representation on each side. For example, if you want to limit things to 32-bit signed integers, and send them in big-endian C integer format, the Python code for that is buf = struct.pack('!I', number) and number = struct.unpack('!I', buf).

But you should consider whether you need a binary format. It's obviously harder to read and debug as a human. It's also easier to get wrong (e.g., by forgetting about endianness or word size). And the easy ways to do it are limited (e.g., the !I format described above will fail for numbers bigger than about 2 billion). And it isn't even necessarily more compact. Often, you're sending lots of small numbers, which take 2-3 bytes as strings with newlines, but 4 bytes in binary form.

Here's a simple Python implementation of a line-based number reader:

def read_numbers_off_socket(s):
    buf = ''
    while True:
        newbuf = s.recv(4096)
        if not newbuf:
            yield int(buf)
            break
        buf += newbuf
        lines = buf.split('\n')
        for line in lines[:-1]:
            yield int(line)

But you can do it even more simply with s.makefile:

def read_numbers_off_socket(s):
    with s.makefile() as f:
        for line in f:
            yield int(line)

Upvotes: 2

woozyking
woozyking

Reputation: 5220

It's hard to tell from your client code in terms of what kind of client library you used to establish the TCP connection.

Why don't you use some message queue implementations that have support for C# and Python, such as ZeroMQ? If you needed more complexity in the data structure passing around, you could also consider using some in memory key-value store solutions to implement queues, such as Redis. The advantage would be that the message queue server/client implementations are well designed and you just have to make one or two lines of code to send/recv in your business logic.

Upvotes: 2

Related Questions