이전포스트

[C/Java] C와 java간 소켓통신에서 주의할 점!!!

freemmer 2011. 6. 7. 16:10
출처 : http://www.javaservice.com/~java/bbs/write.cgi?m=&b=qna2&c=w_f&n=1221737969&p=1&s=t
 

안녕하세요 java와 c간의 TCPIP통신을 하고 있는데요 커넥트가 안되는 문제가 발생했었는데 그건 제 실수로 해결이 되었고 이번에 서로 통신을 해보니까 특이한 사항이 생겨서 질문을 드립니다. 구조는 에코 서버입니다. C가 서버이구요 자바가 클라이언트 입니다. 처음 서버가 열리구 클라이언트가 접속을 하고 자바에서 메세지를 입력받아서 서버에 전송을 하게 되어 있습니다. 같은 인디언체계에서 전송을 하기에 인디언 문제도 안생기구요 그런데 서버측에서는 accept 때와 매번 메세지가 전송이 될때 마다 특이한 문자가 들어옵니다. 혹시나 해서 아래처럼 반복문으로 바이너리 값을 찍어봤습니다. printf("[%02x]\n",(unsigned char)message[i]); ы [ac] [ed] [00] [05] thello? [74] [00] [07] [68] [65] [6c] [6c] [6f] [c0] [80] hijung? [74] [00] [08] [68] [69] [6a] [75] [6e] [67] [c0] [80] 이런식으로 나옵니다. 접속할때 클라이언트에게로 그대로 다시 전달해서 클라이언트에서 화면을 찍을때는 정상적인 값으로 보입니다. 일단 string 에다가 마지막에 "\0"을 붙여줬지만 안됩니다.(80이란값이 매번찍힘) ex) sendData + "\0" //sendData는 전송될 데이터를 가지고 있음 74 00 07 이런값이 뜨고 마지막에 07같은경우에는 전송된 문자열의 길이인거 같습니다. 클라이언트에서 스트림을 ObjectInputStream , ObjectOutputStream을 쓰고 있는데 여기 사이트에 자료를 조금 검색해보니 쓰면 안된다는 식으로 나왔던데요.. 제가 자바초보라서 저걸 안쓰면 어떤걸써서 적용을 시키는지...실제 적용을 할줄 몰라서;; 어떠한 문자열에 대한 차이 때문이거나 전송방식의 차이가 있는거 같은데 C에서는 앞부분도 문자열로 취급하고 출력하기에 가령 값을 저장한다든지에서 문제가 생길꺼 같은데요 이부분을 통일 시켜줄수 없을까요? 되도록이면 java단에서 고쳐야됩니다. 다른부분은 상사가 만들고 있어서요 ㅠ
제목 : Re: 그냥 OutputStream을 사용하시면 됩니다.
글쓴이: 너스(guest) 2008/09/19 09:30:27 조회수:914 줄수:26

OjbectOutputStream은 객체를 Serailaization 시켜서 보내는 기능을 합니다.
따라서, 객체에 대한 정보가 같이 넘어갑니다.
그래서, Java가 아닌 타 언어로 통신하실 때는 사용하시면 안됩니다.
C가 Java의 Serialization 형식을 알 수가 없기 때문입니다.

그냥, OutputStream을 사용하시면 됩니다.

socket에서 얻은 OutputStream을 그냥 사용하셔도 되고요,
주고 받는 데이터가 많다면, BufferredOutputStream을 사용하시면 됩니다.

예를 들어,

 BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());

 String s = "hello";

 byte[] data = s.getBytes();
 bos.write(data);
 bos.flush();

이렇게 사용하시면 됩니다.

InputStream도 마찬가지로 사용하시면 됩니다.

--
제목 : Re: 다른 에러가 발생합니다.
글쓴이: 박정순(anaud2) 2008/09/19 15:39:43 조회수:1004 줄수:78

답변 감사합니다.
일단은 InputStream과 OutputStream으로 사용을 해보고 에러가 생겨서 
BufferedInputStream,BufferedOutputStream으로 사용을 해봤지만 똑같은 에러가
발생을 합니다.
java.lang.NullPointerException
        at java.net.SocketInputStream.read(SocketInputStream.java:88)
        at EchoServerEx.<init>(EchoServerEx.java:103)
        at EchoServerEx.main(EchoServerEx.java:122)

위의 에러는 java서버와 java클라이언트간 통신을 할때 input,outputstream을쓴 서버의 에러입니다.
BufferedInputStream,BufferedOutputStream 을 사용해서 해서 C와 통신을 할때도
똑같은 에러가 발생을 합니다. 중간 socket이란 글짜가 Filter로 바뀌어져 있습니다.

종합해보면 두개다 사용해서 비슷한 에러가 발생합니다. java간이나 c와 할때도 같습니다.
C로 통신을 해보면 서버에는 글자가 찍히는데 c서버가 클라이언트로 전송을 하면 읽을때
저런에러가 발생하는거 같습니다.

자바간에는 클라이언트가 접속요청을 하면 저렇게 되는것같구요...
제가 read하는부분을 혹시 틀렸을지 몰라서 밑에 소스를 가져왔습니다. 
BufferedInputStream을 사용한 클라이언트 입니다.
한가지 문제는 해결됐지만 새로운 에러가 생겨서 부탁드립니다.(_ _)



import java.net.*;
import java.io.*;
public class  Test{
  String ipAddress;        //접속을 요청할 서버의 아이피 주소와 
  int    port;              //포트 번호 
  Socket client=null;       //클라이언트 소켓
  BufferedReader read;    //키보드로부터 메시지를 읽어올 입력 스트림 
  InputStream is;          //서버가 보낸 데이터를 읽기 위한 입력 스트림 저장
  ObjectInputStream ois;   //서버로부터 데이터를 전송받기 위한 스트림
  OutputStream os;        //서버로 메시지를 보내기 위한 출력 스트림 저장
  ObjectOutputStream oos; //서버에 데이터를 전송하기 위한 스트림
  String sendData;         //서버로 보낼 데이터를 저장하기 위한 변수  
  String receiveData;      //서버로부터 받은 데이터를 저장하기 위한 변수 
  byte[] send;
  byte[] recv;
  BufferedOutputStream bos;
  BufferedInputStream bis;

  public Test(String ip, int p)  {
    ipAddress=ip;
    port=p;
    try{
      System.out.println("**** 클라이언트*****");
      client = new Socket(ipAddress, port); 
      read= new BufferedReader(new InputStreamReader(System.in));

      os = client.getOutputStream();
      bos = new BufferedOutputStream(client.getOutputStream());
      bis = new BufferedInputStream(client.getInputStream());
    
     System.out.print("입력 ->");
     while((sendData = read.readLine()) != null){ 
	send = sendData.getBytes();
	bos.write(send);
	bos.flush();
	  if(sendData.equals("quit"))
			break;
	bis.read(recv);
           System.out.println(client.getInetAddress()+"로부터 받은 메시지(에코 됨):"+recv);
	        System.out.print("입력 ->");
	  }
      bis.close();
      bos.close();
    }catch(Exception e){    
      e.printStackTrace();  //에러 메시지를 출력하고
      System.exit(0);       //프로그램을 종료한다. 
    }
  }

  public static void main(String[] args) {
    new Test("192.168.1.4", 2200);//포트 번호 5000을 오픈한다. 
  }
}
제목 : Re: 예제를 보면
글쓴이: 조정환(lovemini) 2008/09/25 17:20:52 조회수:939 줄수:20

저 예제만을 놓고 보면...

bis.read(recv);

라고 하셨는데 recv 는 초기화 되어 있지 않습니다. 즉 null 상태이기 때문에 

NullPointerException 이 발생합니다.

recv = new byte[1024]; 와 같이 메모리 영역을 할당해 주세요.



한가지 덧붙이자면 BufferedInputStream 을 사용하신다면 위와 같이 하시지 마시고

String data = bis.readLine();

로 하시면 한줄 한줄 읽어오므로 편리합니다.

단, 서버에서 LF 를 꼭 붙인다는 전제하에서.

반응형