2008. 12. 12. 13:58

질문 sun.io.MalformedInputException에 대해서




네트웍 통신시 아래와 같은 에러가 발생합니다.
혹 이런 에러에 대해서 아시면 한수 가르침좀 부탁드립니다.
소스는 아래쪽에 써놓았습니다.

READ ERROR : null : sun.io.MalformedInputException
        at sun.io.ByteToCharDoubleByte.flush(ByteToCharDoubleByte.java:51)
        at java.io.InputStreamReader.flushInto(InputStreamReader.java:154)
        at java.io.InputStreamReader.fill(InputStreamReader.java:178)
        at java.io.InputStreamReader.read(InputStreamReader.java:249)
        at java.io.BufferedReader.fill(BufferedReader.java:139)
        at java.io.BufferedReader.readLine(BufferedReader.java:299)
        at java.io.BufferedReader.readLine(BufferedReader.java:363)
        at it21.acom_tcplib.RecvMsg_FromTcp(acom_tcplib.java:97)
        at incheon_segu_daily.Send_Message(incheon_segu_daily.java:273)
        at incheon_segu_daily.Get_Result(incheon_segu_daily.java:166)
        at incheon_segu_daily.service(incheon_segu_daily.java:142)
        at xecure.servlet.XecureHttpServlet.service(XecureHttpServlet.java:261)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:274)
        at jeus.servlet.engine.ServletWrapper.execSingleThreadServlet(ServletWrapper.java:222)
        at jeus.servlet.engine.ServletWrapper.execServlet(ServletWrapper.java:236)
        at jeus.servlet.engine.ApacheRequestProcessor.run(ApacheRequestProcessor.java:85)

아래 소스 main에서 보면 args[0]는 1인 경우에는 위와 같은 에러가 발생하고
1이 아닌 경우에는 제대로 데이터를 받습니다.
물론 위의 에러를 일으킨 소스는 웹쪽에서 서비스 되는 건데
아래의 소스와 같은 라이브러리를 사용합니다.

왜인지 아무리 생각해도 모르겠네요..
두 소스의 차이점은 args[0]는 1인 경우는 BufferedReader를 사용했고
아닌경우는 DataInputStream을 사용했다는 차임점인데 잘 모르겠습니다.

참고로 통신서버는 SUN 솔라리스이고 서블릿 엔진은 JEUS를 사용했습니다.

import java.io.*;
import java.net.*;
import java.util.*;
import java.text.*;
import java.util.Date;

public class TcpNet {
	public static void main(String args[]){
		Socket sock = null;
		String url = "210.112.177.2";
		String port="8300";
		String sendMsg = send();
		String recvMsg = null;
		int len = sendMsg.length();
		long timelimit=10000 ;

		System.out.println("SEND=["+sendMsg+"]");
		if( args[0].equals("1") ) {
			try{ 
				sock = connect( url, port );
				send1( sock, sendMsg, len, timelimit );
				recvMsg = read1( sock, timelimit );
			}catch(Exception e){
				e.printStackTrace();
			}finally{
				close(sock);
			}
		} else {
			try{
				sock = connect( url, port );
				send2( sock, sendMsg, len, timelimit );
				recvMsg = read2( sock, timelimit );
			}catch(Exception e){
				e.printStackTrace();
			}finally{
				close(sock);
			}
		}
		System.out.println("RECV=["+recvMsg+"]");
		System.exit(0);
	}

	public static String send() {
		//지방세 조회 EFFV
		String sendMsg = "TEMP20020209Y                      000000000000000000000000                                                                  0000000000000                000000000000000000                                                                  0000000000000                000000000000000000                                                                  0000000000000                000000000000000000                                                                  0000000000000                000000000000000000                                                                  0000000000000                000000000000000000                                                                  0000000000000                000000000000000000                        ";
		return sendMsg;
	}

	public static Socket connect(String url, String port) throws Exception {
		Socket client;
		//첫글자가 숫자면 ip 로처리
		if(Character.isDigit(url.charAt(0))) {
			client = new Socket(url, Integer.parseInt(port));
		}else{
       		InetAddress url_ = InetAddress.getByName(url);
       		client = new Socket(url_, Integer.parseInt(port));
		}
		return client;
	}

	public static void send1(Socket sock, String sendMsg, int len, long timelimit) {
		try {
		   sock.setTcpNoDelay(true);
           PrintWriter pw = new PrintWriter( new OutputStreamWriter( sock.getOutputStream() ), true );
           pw.print( sendMsg );
           pw.flush();
		} catch(Exception e) {
			close(sock);
			e.printStackTrace();
		}
	}

	public static void send2(Socket sock, String sendMsg, int len, long timelimit) {
		OutputStream pw = null;
		try {
			sock.setSoTimeout( (int)timelimit); 
			pw = sock.getOutputStream();
			byte[] b=sendMsg.getBytes();
			pw.write(b);
			pw.flush();
		}catch(Exception e){
			if(pw!=null){ try{ pw.close(); }catch(IOException ioe){} }
			close(sock);
			e.printStackTrace();
		}
	}

	public static String read1(Socket sock, long timelimit){
        String recvMsg = "";
		BufferedReader br=null;
		try {
			sock.setSoTimeout( (int)timelimit );   // 수신제한시간 설정 milli sec ( 1분 )
			br = new BufferedReader( new InputStreamReader( sock.getInputStream() ) );
            String line = null;
			int i = 0;
            while( ( line = br.readLine() ) != null ) {
              recvMsg += line;
            }
            br.close();
		} catch(Exception e) {
			close(sock);
			e.printStackTrace();
		}
	
		return recvMsg;
	}

	public static String read2(Socket sock, long timelimit){
        String recvMsg = "";
		DataInputStream in = null; 
		byte[] recvData = new byte[1024];

		try {
			sock.setSoTimeout( (int)timelimit); 	
			in = new DataInputStream(sock.getInputStream() );

			int i = 0, start_pos = 0;
			i = in.read( recvData );

			recvMsg = new String(recvData);

		}catch(Exception e){
			e.printStackTrace();
			return null;
		}finally{
			if(in!=null){ try{ in.close(); }catch(IOException ioe){} }
			if(sock!=null){ try{ sock.close(); }catch(IOException ioe){} }
		}
		return recvMsg;
	}

	public static void close(Socket client) {
		try {
			client.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
제목 : Re: 질문 sun.io.MalformedInputException에 대해서
글쓴이: 김완석(kinyang) 2002/02/19 10:15:11 조회수:1761 줄수:66
>
> {질문 sun.io.MalformedInputException에 대해서}
> {손님(guest), lsk7up@hanmail.net}
>
> 네트웍 통신시 아래와 같은 에러가 발생합니다.
> 혹 이런 에러에 대해서 아시면 한수 가르침좀 부탁드립니다.
> 소스는 아래쪽에 써놓았습니다.
> 
> READ ERROR : null : sun.io.MalformedInputException
>         at sun.io.ByteToCharDoubleByte.flush(ByteToCharDoubleByte.java:51)
>         at java.io.InputStreamReader.flushInto(InputStreamReader.java:154)
>         at java.io.InputStreamReader.fill(InputStreamReader.java:178)
>         at java.io.InputStreamReader.read(InputStreamReader.java:249)
>         at java.io.BufferedReader.fill(BufferedReader.java:139)
>         at java.io.BufferedReader.readLine(BufferedReader.java:299)
>         at java.io.BufferedReader.readLine(BufferedReader.java:363)
>         at it21.acom_tcplib.RecvMsg_FromTcp(acom_tcplib.java:97)
>         at incheon_segu_daily.Send_Message(incheon_segu_daily.java:273)
>         at incheon_segu_daily.Get_Result(incheon_segu_daily.java:166)
>         at incheon_segu_daily.service(incheon_segu_daily.java:142)
>         at xecure.servlet.XecureHttpServlet.service(XecureHttpServlet.java:261)
>         at javax.servlet.http.HttpServlet.service(HttpServlet.java:274)
>         at jeus.servlet.engine.ServletWrapper.execSingleThreadServlet(ServletWrapper.java:222)
>         at jeus.servlet.engine.ServletWrapper.execServlet(ServletWrapper.java:236)
>         at jeus.servlet.engine.ApacheRequestProcessor.run(ApacheRequestProcessor.java:85)
> 
> 아래 소스 main에서 보면 args[0]는 1인 경우에는 위와 같은 에러가 발생하고
> 1이 아닌 경우에는 제대로 데이터를 받습니다.
> 물론 위의 에러를 일으킨 소스는 웹쪽에서 서비스 되는 건데
> 아래의 소스와 같은 라이브러리를 사용합니다.
> 
> 왜인지 아무리 생각해도 모르겠네요..
> 두 소스의 차이점은 args[0]는 1인 경우는 BufferedReader를 사용했고
> 아닌경우는 DataInputStream을 사용했다는 차임점인데 잘 모르겠습니다.
> 

 MalformedInputException 을 구지 해석하자면 ...

 잘못된 형식의 입력으로 error 발생한 것입니다.

 문제의 원인은 Stream의 끝에서 에러가 발생한 듯 싶습니다.

 DataInputStream 을 사용했을 때에는 문제가 없고 BufferedReader 를 사용했을때
 
 문제가 발생하는것은..

 DataInputStream 는 한바이트씩 읽어서 처리하지만,

 BufferedReader 는 2바이트를 읽어 하나의 char로 변환합니다.
 
 위의 MalformedInputException 은 이 과정에서 발생한 듯 싶습니다.
 
 한 바이트를 읽고 난 다음에 다음 바이르틀 읽어 하나의 Char를 만들려다가 
 실패한 것이지요 ...

 제가 소스를 전체적으로 살펴본것은 아니지만, 

 네트웍 상에서는 데이터의 전송을 \r\n으로 구분지어서 전송합니다 ....

 전송되는 데이터의 끝에 \r\n을 추가하여 전송해 보세요 ...

 음냥... 

 그럼 수거하세요 ...

출처 : javasevice.net