오늘은 어디로 갈까...

즐거운 프로젝트 본문

넋두리

즐거운 프로젝트

剛宇 2009. 10. 6. 15:50
...가, 되고 싶었지만.... 역시 암울한 프로젝트가 되어가고 있다.

 일정 관리도 안되고, 갑~의 횡포에 을~은 깨갱~~(본인은 정이다 --;), 한달도 안남았는데, 아직 디자인도 안나오고... 거기다 기획까지 조금 거시기~하고. 후후후... 막판에 고생을 할 생각을 하니 한숨만 나온다.

 CDC.. 아니 CLDC인가... 암튼 자바 1.3버젼 수준에서 개발을 하려니 많이 괴롭다. 그동안 너무 1.5에 익숙해져 있었던탓인지, 많은 것들을 새롭게 개발(?)해야하는것이다. 가장 큰 문제였던게, URLConnection의 timeout 지정문제였다. 여기서는 전혀 신경을 안쓰고 있기에, 그냥 모른척하고 지나가면 되는것이나... 본인의 그릇된 욕심으로 timeout을 지정하고 싶었다. 구글한테 물어봤더니, 여러가지 방법이 나왔으나, STB에서 정상적으로 작동할지 알 수가 없어서, 그냥 Socket을 사용해 직접 만들었다. Socket을 이용해서 GET 방식으로 호출하고, 응답 결과를 받아오는것이다. 헤더(header)를 정확히 분석하지 않지만, 뭐 작동은 하는거 같으니 그냥 사용해볼까 생각중이다.
 거짓말이다. 반만 정상 작동한다. setSoTimeout은 연결되었을때 읽어들이는 패킷이 없을 경우 타임아웃을 설정하는것이다. 연결할때 타임아웃도 체크하려면...... 어떻하면 좋을까? --; 쓰레드 형님을 불러야하나.. ㅠㅠ
		Socket socket = new Socket(host, port);
		if (timeout > 0) {
			socket.setSoTimeout(timeout);	
		}
		
		StringBuffer header = new StringBuffer();
		header.append("GET ").append(path).append(" HTTP/1.1").append(CRLF);
		header.append("Host: ").append(host).append(CRLF);
		header.append("Connection: close").append(CRLF);
		header.append("User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)").append(CRLF);
		header.append("Accept-Encoding: gzip, deflate").append(CRLF);
		header.append("Cache-Control: no").append(CRLF);
		header.append("Accept-Language: ko").append(CRLF);
		header.append(CRLF);
		header.append(CRLF);
		
		BufferedReader reader = null;
		PrintWriter writer = null;
		try {
			writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())));
			
			// 요청 보내기
			if (Logger.isDebugEnable()) {
				Logger.debug(this, "***********************************************");
				Logger.debug(this, "> Request Sending");
				Logger.debug(this, "***********************************************");
				Logger.debug(this, header.toString());
			}
			
			writer.print(header.toString());
			writer.flush();
			
			if (Logger.isDebugEnable()) {
				Logger.debug(this, "***********************************************");
				Logger.debug(this, "> Request Sended");
				Logger.debug(this, "> Waiting Response...");
				Logger.debug(this, "***********************************************");
			}
			
			// 원칙적으로는 헤더를 분석한후 charset을 읽어와야하지만 귀찮아서 그냥 둔다.
			reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), charset));
			
			
			StringBuffer contentSB = new StringBuffer();
			boolean isContent = false;
			String line = null;
			for (int i = 0; (line = reader.readLine()) != null; i++) {
				if (isContent) {
					contentSB.append(line);
				} else {
					if (line.startsWith("HTTP/1.1")) {
						String[] array = StringUtils.toArray(line, " ");
						statusCode = Integer.parseInt(array[1]);
					}
				}
				if (isContent == false && "".equals(line)) {
					isContent = true;
				}
			}
			
			content = contentSB.toString();
		} finally {
			if (reader != null) try { reader.close(); } catch (IOException ie) {}
			if (writer != null) try { writer.close(); } catch (Exception ie) {}
			if (socket != null) try { socket.close(); } catch (IOException ie) { }
		}


좌절(?)을 딛고, 쓰레드로 구현해본 타임아웃 소켓. 정상 작동 여부는 미지수이다.. 뭔가 엉성하긴 하다. 매번 쓰레드가 생성된다는것. 잘못하면 삑사리가 날 수도 있을거 같다... 요즘 세상에는 뭐 쓸일이 없으니...
import java.io.IOException;
import java.net.Socket;

public class SocketHelper implements Runnable {
	
	private String host;
	private int port;
	
	private Socket socket;
	private boolean hasTimeout;
	
	public SocketHelper(String host, int port) {
		this.host = host;
		this.port = port;
	}

	
	public static Socket createSocket(String host, int port, long connectionTimeout) throws IOException {
		SocketHelper sf = new SocketHelper(host, port);
		Thread thread = new Thread(sf);
		thread.start();
		try {
			thread.join(connectionTimeout);
		} catch (InterruptedException ie) {
			thread.interrupt();
		}
		if (sf.socket == null) {
			sf.hasTimeout = true;
			throw new IOException("Socket Connection timeout: " + host + ":" + port);
		}
		return sf.socket;
	}

	public void run() {
		hasTimeout = false;
		try {
			socket = new Socket(host, port);
		} catch (IOException ie) {
		}
		if (hasTimeout) {
			if (socket != null) {
				try { socket.close(); } catch(IOException ie) {}
			}
			socket = null;
		}
	}
}



아래는 URLEncoder와 URLDecoder다, charset을 넣는 메소드가 없어서, 구현하려다 귀찮아서 어딘가에서 가져온것인데, 출처는 모르겠다.
import java.io.UnsupportedEncodingException;

public class URLEncoder {
	
	private static final String hex = "0123456789ABCDEF";
	
	private URLEncoder() {
	}

	/**
	 * This method translates the passed in string into x-www-form-urlencoded
	 * format using the default encoding. The standard encoding is "UTF-8", and
	 * the two-argument form of this method should be used instead.
	 * 
	 * @param s
	 *            The String to convert
	 * 
	 * @return The converted String
	 * 
	 * @deprecated
	 */
	public static String encode(String s) {
		try {
			// We default to 8859_1 for compatibility with the same
			// default elsewhere in the library.
			return encode(s, System.getProperty("file.encoding", "8859_1"));
		} catch (UnsupportedEncodingException uee) {
			// Should never happen since default should always be supported
			return s;
		}
	}

	/**
	 * This method translates the passed in string into x-www-form-urlencoded
	 * format using the character encoding to hex-encode the unsafe characters.
	 * 
	 * @param s
	 *            The String to convert
	 * @param encoding
	 *            The encoding to use for unsafe characters
	 * 
	 * @return The converted String
	 * 
	 * @exception UnsupportedEncodingException
	 *                If the named encoding is not supported
	 * 
	 * @since 1.4
	 */
	public static String encode(String s, String encoding)
			throws UnsupportedEncodingException {
		if (s == null) {
			return null;
		}
		int length = s.length();
		int start = 0;
		int i = 0;

		StringBuffer result = new StringBuffer(length);
		while (true) {
			while (i < length && isSafe(s.charAt(i))) {
				i++;
			}

			// Safe character can just be added
			result.append(s.substring(start, i));

			// Are we done?
			if (i >= length) {
				return result.toString();
			} else if (s.charAt(i) == ' ') {
				result.append('+'); // Replace space char with plus symbol.
				i++;
			} else {
				// Get all unsafe characters
				start = i;
				char c;
				while (i < length && (c = s.charAt(i)) != ' ' && !isSafe(c)) {
					i++;
				}

				// Convert them to %XY encoded strings
				String unsafe = s.substring(start, i);
				byte bytes[] = unsafe.getBytes(encoding);
				for (int j = 0; j < bytes.length; j++) {
					result.append('%');
					int val = bytes[j];
					result.append(hex.charAt((val & 0xf0) >> 4));
					result.append(hex.charAt(val & 0x0f));
				}
			}
			start = i;
		}
	}

	/**
	 * Private static method that returns true if the given char is either a
	 * uppercase or lowercase letter from 'a' till 'z', or a digit froim '0'
	 * till '9', or one of the characters '-', '_', '.' or '*'. Such 'safe'
	 * character don't have to be url encoded.
	 */
	private static boolean isSafe(char c) {
		return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
				|| (c >= '0' && c <= '9') || c == '-' || c == '_' || c == '.' || c == '*');
	}


}

import java.io.UnsupportedEncodingException;

public class URLDecoder {

	private URLDecoder() {
	}

	/**
	 * This method translates the passed in string from x-www-form-urlencoded
	 * format using the default encoding "UTF-8" to decode the hex encoded
	 * unsafe characters.
	 * 
	 * @param s
	 *            the String to convert
	 * 
	 * @return the converted String
	 * 
	 * @deprecated
	 */
	public static String decode(String s) {
		try {
			return decode(s, "UTF-8");
		} catch (UnsupportedEncodingException uee) {
			// Should never happen since UTF-8 encoding should always be
			// supported
			return s;
		}
	}

	/**
	 * This method translates the passed in string from x-www-form-urlencoded
	 * format using the given character encoding to decode the hex encoded
	 * unsafe characters.
	 * 
	 * This implementation will decode the string even if it contains unsafe
	 * characters (characters that should have been encoded) or if the two
	 * characters following a % do not represent a hex encoded byte. In those
	 * cases the unsafe character or the % character will be added verbatim to
	 * the decoded result.
	 * 
	 * @param s
	 *            the String to convert
	 * @param encoding
	 *            the character encoding to use the decode the hex encoded
	 *            unsafe characters
	 * 
	 * @return the converted String
	 * 
	 * @exception UnsupportedEncodingException
	 *                If the named encoding is not supported
	 * 
	 * @since 1.4
	 */
	public static String decode(String s, String encoding)
			throws UnsupportedEncodingException {
		// First convert all '+' characters to spaces.
		String str = s.replace('+', ' ');

		// Then go through the whole string looking for byte encoded characters
		int i;
		int start = 0;
		byte[] bytes = null;
		int length = str.length();
		StringBuffer result = new StringBuffer(length);
		while ((i = str.indexOf('%', start)) >= 0) {
			// Add all non-encoded characters to the result buffer
			result.append(str.substring(start, i));
			start = i;

			// Get all consecutive encoded bytes
			while ((i + 2 < length) && (str.charAt(i) == '%')) {
				i += 3;
			}
			
			// Decode all these bytes
			if ((bytes == null) || (bytes.length < ((i - start) / 3))) {
				bytes = new byte[((i - start) / 3)];
			}

			int index = 0;
			try {
				while (start < i) {
					String sub = str.substring(start + 1, start + 3);
					bytes[index] = (byte) Integer.parseInt(sub, 16);
					index++;
					start += 3;
				}
			} catch (NumberFormatException nfe) {
				// One of the hex encoded strings was bad
			}

			// Add the bytes as characters according to the given encoding
			result.append(new String(bytes, 0, index, encoding));

			// Make sure we skip to just after a % sign
			// There might not have been enough encoded characters after the %
			// or the hex chars were not actually hex chars
			// (NumberFormatException)
			if (start < length && s.charAt(start) == '%') {
				result.append('%');
				start++;
			}
		}

		// Add any characters left
		if (start < str.length()) {
			result.append(str.substring(start));
		}
			

		return result.toString();
	}

}