반응형

 

 

http://blog.naver.com/a96751877/120051201289

 

C/C++ Struct와 JAVA간 소켓통신

C프로그램간에 서버/클라이언트의 관계로 통신하는 경우 struct로 메시지를 선언하여 사용하는 경우가 많습니다.
이경우 struct로 socket write하고 struct로 socket read하기 때문에 어려움이 없습니다. (char *)로 type casting만 해주면 알아서 변환이 되지요..

예를 들면

#include <fstream>
#include <iostream>
using namespace std;

typedef struct _score
{
 char name[10];
 int  price;
 short cnt;
} score;

int main()
{
 score data[2] = {
 {"강아지", 2000, 10},
 {"멍멍이", 3000, 5}
 };
 score test[2];

 ofstream fout;
 fout.open("iodata.bin");
 fout.write((char *)data, sizeof(data));
 fout.close();

 ifstream fin;
 fin.open("iodata.bin", ios::binary);
 fin.read((char *)&test, sizeof(test));
 fin.close();

 for(int i = 0; i < 2; i++)
  cout << test[i].name << " : " << test[i].price << endl;

 return 0;
}

하지만 자바와 통신을 하는 경우는 상황이 달라집니다...
자바에서는 struct라는 형식이 없기때문이죠.
만약 통신하는 데이터값이 ascii값으로만 이루어져있다면 문제가 되지 않습니다.
하지만 int, short등의 data type이 존재하면 binary값으로 넘어오게되어 자바에서 InputStream으로 String에 받아서 그냥 출력해보면 데이터가 깨지게 됩니다...
다음은 이를 해결한 소스 예제입니다.
자바가 소켓서버역할을 하는 프로그램입니다.

import java.net.*;
import java.io.*;

public class SocketServerThread extends Thread {
 
 private Socket socket = null;
 
 public SocketServerThread (Socket socket) {
  this.socket = socket;
 }
 
 public void run() {
 
 try {

  byte bbuf[] = new byte[MSG_LENGTH];
  MessageVO mvo = new MessageVO();
  int readSize = 0;
  
  while ( (readSize=in.read(bbuf)) > 0 ) {
   byte[] tmpArr = null;
   tmpArr = new byte[30];
   System.arraycopy(bbuf, 0, tmpArr, 0, 10);  
   mvo.name= new String(tmpArr);   

   tmpArr = new byte[30];  
   System.arraycopy(bbuf, 10, tmpArr, 0, 4);
   mvo.price= getInt(tmpArr);

   tmpArr = new byte[30];  
   System.arraycopy(bbuf, 14, tmpArr, 0, 2);
   mvo.price= getShort(tmpArr);

    System.out.println(mvo);
  }
  
  out.close();
  in.close();
  socket.close();
  
  } catch (SocketException e) {
  
   e.printStackTrace();
  
  } catch (IOException e) {

   e.printStackTrace();
  
  }
 }

 public int getInt(byte[] bt) {

  int temp = 0;
  int[] bt2 = new int[4];

  for(int i = 0; i < 4; i++) {
   bt2[i] = bt[i] < 0 ? ( Byte.MAX_VALUE + 1 ) * 2 + bt[i] : bt[i];
   temp |= bt2[i] << 8*(3-i);
  }
 
  return temp;
 
 }

 public short getShort(byte[] bt) {

   short temp = 0;
   short[] bt2 = new short[2];

   for(int i = 0; i < 2; i++) {
    bt2[i] = bt[i] < 0 ? (short)(( Byte.MAX_VALUE + 1 ) * 2 + bt[i]) : bt[i];
    temp |= bt2[i] << 8*(1-i);
   }
 
   return temp;
 
  }
 }

 class MessageVO {
  
  String name;
  int price;
  short cnt;
  
  public String toString() {
    return new StringBuffer()
    .append("name : "+name)
    .append("price : "+price)
    .append("cnt : "+cnt)
    .toString();
  }
  
 }
 
}


 

 

JAVA 와 C 간의 TCP 통신시 Endian 처리 === C & C++ ===/System & Net 2008/11/18 22:40


두 다른 언어를 TCP 로 연결할때 플랫폼이 다르다면 시스템이 little-Endian / Big-Endian 인지 확인하여야한다.
일반적으로 Linux 은 little-Endian Windows 는 Big-Endian 을 사용한다. ( 시스템 마다 차이 있을수 있음 )

Server ( Linux C )
Client (windows JAVA) 일경우에는 ..

C 에서 받은 버퍼를 받아 Endian 처리를 다음과 같이 변환하여야한다. (int 자료형 등을 받을때)

/**
   * Java는 모든 플렛폼에서 정수를 표현할 때 Big-Endian 방식을 사용한다.

   * Little-Endian을 사용하는 플렛폼에서 보낸 이진데이터를 받을 경우
     Big-Endian으로 변환하여 사용해야한다.

   * 다음은 자바에서 Big Little Endian변환을 수행하는 로직이다.
   */

public class Endian{
  /**
   * 자바에서 사용하는 Big-Endian 정수값을 Little-Endian 바이트 배열로 변환한다.
   */

  public static byte[] getLittleEndian(int v){
       byte[] buf = new byte[4];
       buf[3] = (byte)((v >>> 24) & 0xFF);
       buf[2] = (byte)((v >>> 16) & 0xFF);
       buf[1] = (byte)((v >>>  8) & 0xFF);
       buf[0] = (byte)((v >>>  0) & 0xFF);
       return buf;
  }
 
  /**
   * Little-Endian 바이트 배열을 자바에서 사용하는 Big-Endian정수로 변환한다.
   */
  public static int getBigEndian(byte[] v)throws Exception{
       int[] arr = new int[4];
       for(int i=0;i<4;i++){
            arr[i] = (int)(v[3-i] & 0xFF);
       }
       return ((arr[0]  << 24) + (arr[1]  << 16) + (arr[2]  << 8) + (arr[3]  << 0));
   }
}


C <--> JAVA 통신 설정시 잘못된 값이 나올수 있기 때문에, 이유 정도는 알아둘 필요가 있다.
이것이 구찮다면 전부 byte 로 보내자 ..;;

소스출처: http://blog.naver.com/joodong1027?Redirect=Log&logNo=130023035042 

 

 

 

 

증권전산원 증권정보(C Socket --> Java Socket Client)

 

http://www.javaservice.com/~java/bbs/read.cgi?b=consult&c=r_p&n=957503744

 

 

 

자체 수정   INT

 

 

==============================================================

 

 

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedInputStream;

import java.util.*;

import java.net.InetAddress;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;

import java.nio.*;

public class SocketClient
{

 public static void main(String[] args) throws Exception{

  Socket socket = null;
  String ip = "127.0.0.1";
  int port = 8888;

  BufferedOutputStream bout = null;
  BufferedInputStream bin = null;

  try {

   socket = new Socket(ip,port);  //소켓생성
   socket.setSoTimeout(6*1000);   //TIMEOUT6초

   bout = new BufferedOutputStream(socket.getOutputStream()); //보내는 데이타
   bin = new BufferedInputStream(socket.getInputStream());    //받는 데이타

   byte[] buffer = new byte[200];

   putInt(0, buffer, 0);
   putInt(100, buffer, 4);  // 100

   System.out.println("send packet--->["+new String(buffer) + "]");
   System.out.println("send size  --->["+buffer.length  + "]");

   bout.write(buffer);   // 스트림을 바이트배열 형식으로 서버에 보낸다
   bout.flush();         // 버퍼 내용을 비운다

  }
  catch (SocketException e1) {
   System.out.println("SOCKET EXCEPTION : "+e1.toString());
  } catch (UnknownHostException e) {
   System.out.println("Server Address Error");
  } catch (Exception e2) {
   System.out.println("EXCEPTION :"+e2.toString());
  } finally {

  if(bout!=null){

   try {
    bout.close();
   }catch(Exception e3){
    System.out.println("EXCEPTION :"+e3.toString());
   }

  }

   if(bin!=null){

   try{
     bin.close();
   }catch(Exception e4){
    System.out.println("EXCEPTION :"+e4.toString());
   }

  }

  System.out.println("Socket Closing....");
  socket.close();

  }

  // return  result;

 }

 public static final byte[] getbytes(byte src[], int offset, int length)
 {
  byte dest[] = new byte[length];
  System.arraycopy(src, offset, dest, 0, length);
  return dest;
 }

 public static void putInt(int value, byte[] array, int offset)
 {
  array[offset]   = (byte)(0xff & (value >> 24));
  array[offset+1] = (byte)(0xff & (value >> 16));
  array[offset+2] = (byte)(0xff & (value >> 8));
  array[offset+3] = (byte)(0xff & value);
 }

}

 

 

 

==============================================================

 

 

 

반응형
Posted by 공간사랑
,