2016-02-20 32 views
2

我想發送一個整數數組從Java到另一個程序是用C編碼,反之亦然接收。Java:通過套接字發送/接收int數組到/從一個編碼在C程序

我已經從here讀過,我應該在C程序中使用普通的int數組時使用Java中的短數組。

作爲Java的新手,我仍然不確定如何正確執行此操作。以下是我的代碼:

package tcpcomm; 

import java.io.IOException; 
import java.io.PrintWriter; 
import java.net.Socket; 
import java.net.UnknownHostException; 
import java.util.Scanner; 
import java.io.ByteArrayInputStream; 
import java.io.ByteArrayOutputStream; 
import java.io.DataInputStream; 
import java.io.DataOutputStream; 
import java.io.InputStream; 
import java.io.OutputStream; 

import datatypes.Message; 

public class PCClient { 

    public static final String C_ADDRESS = "192.168.1.1"; 
    public static final int C_PORT = 8888; 

    private static PCClient _instance; 
    private Socket _clientSocket; 
     private ByteArrayOutputStream _toCProgram; 
     private ByteArrayInputStream _fromCProgram; 

    private PCClient() { 

    } 

    public static PCClient getInstance() { 
     if (_instance == null) { 
      _instance = new PCClient(); 
     } 
     return _instance; 
    } 

    public static void main (String[] args) throws UnknownHostException, IOException { 
     int msg[] = {Message.READ_SENSOR_VALUES}; 
     ByteArrayOutputStream out = new ByteArrayOutputStream(); 

    PCClient pcClient = PCClient.getInstance(); 
    pcClient.setUpConnection(C_ADDRESS, C_PORT); 
    System.out.println("C program successfully connected"); 
    while (true) { 
     pcClient.sendMessage(out, msg); 
     ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); 
     int[] msgReceived = pcClient.readMessage(in); 
     } 
    } 

    public void setUpConnection (String IPAddress, int portNumber) throws UnknownHostException, IOException{ 
     _clientSocket = new Socket(C_ADDRESS, C_PORT); 
     _toCProgram = new PrintWriter(_clientSocket.getOutputStream()); 
     _fromCProgram = new Scanner(_clientSocket.getInputStream()); 
    } 

    public void closeConnection() throws IOException { 
     if (!_clientSocket.isClosed()) { 
      _clientSocket.close(); 
     } 
    } 

    public void sendMessage(OutputStream out, int[] msg) throws IOException { 
     int count = 0; 
     DataOutputStream dataOut = new DataOutputStream(out); 
     dataOut.writeInt(msg.length); 
     System.out.println("Message sent: "); 
     for (int e : msg) { 
      dataOut.writeInt(e); 
      System.out.print(e + " "); 
      if(count % 2 == 1) 
       System.out.print("\n"); 
      count++; 
     } 
     dataOut.flush(); 
    } 

    public int[] readMessage(InputStream in) throws IOException { 
     int count = 0; 
     DataInputStream dataIn = new DataInputStream(in); 
     int[] msg = new int[dataIn.readInt()]; 
     System.out.println("Message received: "); 
     for (int i = 0; i < msg.length; ++i) { 
      msg[i] = dataIn.readInt(); 
      System.out.print(msg[i] + " "); 
      if(count % 2 == 1) 
       System.out.print("\n"); 
      count++; 
     } 
     return msg; 
    } 
} 

有關如何更正代碼的任何指導讚賞!

我是否需要將流從bytearray更改爲intarray?聽起來像很多轉換..(根據我可以在這裏找到的答案)

+0

您可以使用像ASCII這樣的文本編碼並在兩端進行解析。 C程序的 –

回答

0

要回答你的問題:不,你不需要改變流從byteint。 Java中I/O流的部分屬性是它們基於byte。所以當你想寫一個int到一個流中時,你需要將它拆分成它的byte元素並分別寫入它們。

Java使用4字節的有符號整數,您不能更改它。對於你的對象(你的C程序),你需要確保它使用了一個等效類型,例如stdint.hint32_t。這可以被視爲你的「協議」的一部分。

的Java已經提供了讀取和並與java.io.DataInputStreamjava.io.DataOutputStream流寫intlong等值的裝置。請務必記住DataOutputStream#writeInt(int)int的四個字節從高變低寫入。這叫做Endianness,但我確定你已經知道了。這也可以被認爲是你的「協議」的另一部分。

最後,在傳輸結構時,正在讀取的端點必須知道需要讀取多少。對於固定大小的結構,雙方(客戶端和服務器)都已知道大小,但數組可能會有所不同。所以發送時,你需要告訴你的對方你將發送多少。在數組的情況下,它非常簡單,只需首先發送數組長度(僅另一個int)。這可以被認爲是你的「協議」的又一部分。

我已經寫了一個例子,用於寫入和讀取流向和來自數據流的int數組。

package com.acme; 

import java.io.ByteArrayInputStream; 
import java.io.ByteArrayOutputStream; 
import java.io.DataInputStream; 
import java.io.DataOutputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.OutputStream; 
import java.util.Arrays; 

public class SendAndReceive { 

    public static void main(String[] args) throws IOException { 
     int[] ints = new int[] {Integer.MIN_VALUE, -1, 0, 1, Integer.MAX_VALUE}; 

     ByteArrayOutputStream out = new ByteArrayOutputStream(); 
     writeInts(out, ints); 
     ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); 
     int[] results = readInts(in); 

     if (!Arrays.equals(ints, results)) System.out.println("Damn!"); 
     else System.out.println("Aaall's well!"); 
    } 

    private static void writeInts(OutputStream out, int[] ints) throws IOException { 
     DataOutputStream dataOut = new DataOutputStream(out); 
     dataOut.writeInt(ints.length); 
     for (int e : ints) dataOut.writeInt(e); 
     dataOut.flush(); 
    } 

    private static int[] readInts(InputStream in) throws IOException { 
     DataInputStream dataIn = new DataInputStream(in); 
     int[] ints = new int[dataIn.readInt()]; 
     for (int i = 0; i < ints.length; ++i) ints[i] = dataIn.readInt(); 
     return ints; 
    } 
} 

所有你需要做的是使用的方法writeInts(OutputStream, int[])readInts(InputStream),並與您的插座流調用它們。

因爲沒有標準套接字實現(雖然有Boost庫,但它不是標準的,而不是C但是C++),所以我沒有實現用於演示目的的C程序。

玩得開心!

+0

,我應該將這些添加到C文件的頂部嗎? **#include typedef int int32_t; typedef unsigned int uint32_t; typedef size_t uint32_t; ** –

+0

並感謝您的詳細解釋。幫助我瞭解有關C和Java的更多信息! –

+0

@DoeJoe,沒問題。是的,你需要在源代碼中包含'stdint.h',但是你不需要類型定義(這是頭文件的用途)。取決於你爲'int32_t'編譯的系統本身就是'int'。大部分情況是這樣。但是有幾次不是,'int32_t'被定義爲等同於'int'的東西。它增加了代碼的可移植性。 – Brian

相關問題