2013-02-27 72 views
0

我想從一個C#程序(服務器)運行在PC上,使用套接字技術發送兩個整數到Python客戶端腳本(它運行在Linux機器上)。直到現在我能夠發送字符串。C#發送整數到python

服務器:

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() }); 
    } 
} 

而且客戶端代碼:

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

所以我想「放」到緩衝區數組整數,然後將其發送到python腳本。可能嗎?我究竟做錯了什麼?

+1

在TCP,你不能只是'發送'和'recv'消息,而不需要某種分隔符,頭部等。一個'send'可以在另一端作爲四個'recv'到達,或者與另外三個'send'捆綁在一起。 – abarnert 2013-02-27 21:07:27

回答

2

很難從您的客戶端代碼中知道您用於建立TCP連接的客戶端類型。

爲什麼不使用一些支持C#和Python的消息隊列實現,比如ZeroMQ?如果您在傳遞的數據結構中需要更多的複雜性,您還可以考慮在內存中使用一些鍵值存儲解決方案來實現隊列,例如Redis。優點是消息隊列服務器/客戶端實現設計良好,並且只需要在業務邏輯中發送一行或兩行代碼即可發送/接收。

+1

我第二個ZMQ的建議。我還會使用JSON或Google Protocol Buffers等序列化格式將數據轉換爲「字節」。 – 2013-02-27 21:07:45

+0

@TimothyShields,這將是強大的。但是,如果OP只想發送整數,通過消息隊列實現將它們作爲整數的字符串表示發送並在Python中將它們轉換回int將是安全和簡單的。 – woozyking 2013-02-27 21:11:21

2

在解決「如何發送整數?」這個問題之前,您需要解決一個更大的問題:「我該如何發送消息?」

在TCP中,當您在一側調用send時,即使它一次發送整個緩衝區(不能保證),另一方可能會在多個單獨的recv調用中獲取數據,而不是一次全部調用。更糟糕的是,它可能會在一個recv中得到一個send和下一個send的一部分。

您可以使用更高級別的協議類ZeroMQ甚至是HTTP來爲您處理此問題。但是如果你只是想使用原始的TCP,你必須自己處理。

一個顯而易見的解決方案是一個像換行符(或NUL字節等)的分隔符 - 但當然你需要一些在消息中間轉義換行符的方法。另一種可能性是使用某種標題來描述消息的其餘部分,如netstring。或者你可以使用像JSON這樣的自定義消息類型。

許多真正簡單的處理分隔符問題的方法會自動處理髮送整數。 JSON包含數字作爲一種類型。或者,您可以將整數作爲字符串發送到netstrings或換行符分隔的字符串。

如果你真的想以某種「二進制」的方式對數字進行編碼,你必須選擇一種表示方式,並編寫代碼來轉換每一邊的表示形式。例如,如果您想將事物限制爲32位有符號整數,並以大端C整數格式發送它們,則Python代碼爲buf = struct.pack('!I', number)number = struct.unpack('!I', buf)

但是您應該考慮是否需要二進制格式。閱讀和調試顯然比較困難。錯誤也很容易(例如,忘記字節順序或字的大小)。而簡單的做法是有限的(例如,上述!I格式將失敗的數字大於約20億)。它甚至不一定更緊湊。通常情況下,您會發送很多小數字,這些數字需要2-3個字節作爲帶有換行符的字符串,而4字節則是二進制形式。

這裏有一個簡單的Python實現基於行的數讀者:

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) 

但你可以做到這一點更簡單地s.makefile

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