Project2010.03.10 23:20



만든지 얼마 지나지 않아... 혼자 테스트중 버그들이 발견되어 수정하였습니다.

  • 클라이언트 번호 할당 방식
  • MSGConnectServer 클래스 추가

 

Posted by 초프(초보 프로그래머)
Project2010.03.10 11:12


  • yhg.comm.message
    • Message
      • int getType()
        • 클라이언트 종류 얻기
      • int getNumber()
      • void setNumber(int num)
        • 클라이언트 번호 설정
    • MSGBoolean extends Message
      • void setTrue()
      • void setFalse()
      • boolean get()
    • MSGChat extends Message
      • void setMessage(String str)
        • 채팅 메세지 설정
      • String getMessage()
    • MSGEnterClient extends Message
      • 서버에 클라이언트가 접속하였을 경우 이미 접속한 다른 클라이언트들에게 전송하는 메세지
    • MSGLeaveClient extends Message
      • 서버에 접속되어있는 클라이언트가 접속이 끊겼을 경우 다른 클라이언트들에게 전송하는 메세지
  • yhg.comm.server
    • ICommClientManagerEvent
      • void onReceiveMessage(CommClientManager cm, Message msg)
        • 서버가 클라이언트로부터 메세지를 받았을 때의 이벤트
      • void onSendMessage(CommClientManager cm, Message msg)
        • 서버가 클라이언트에게 메세지를 보낼때의 이벤트
    • ICommServerEvent
      • void onEnterClient(CommClientManager cm)
        • 서버에 클라이언트가 접속하였을 때의 이벤트
      • void onLeaveClient(CommClientManager cm)
        • 서버에서 클라이언트가 떠났을 때의 이벤트
    • CommClientManager
      • CommClientManager(CommServer server, Socket sock) throws IOException
      • void send(Message msg) throws IOException
        • 클라이언트에게 메세지 전송
      • Socket getSocket()
        • 클라이언트 소켓 얻기
      • InetAddress getLocalAddress()
        • 클라이언트 주소 얻기 (소켓을 얻어서 할경우 연결이 끊기면 정보를 잃기 때문에...)
    • CommServer
      • CommServer(int port) throws IOException
      • void setClientManagerEvent(ICommClientManagerEvent rec)
        • 이벤트 설정
      • void setServerEvent(ICommServerEvent apt)
        • 이벤트 설정
      • void sendAll(Message msg) throws IOException
        • 모든 클라이언트에게 메세지 전송
      • void sendAll(int num, Message msg) throws IOException
        • 지정한 클라이언트를 제외하고 메세지 전송
      • void sendTo(int num, Message msg) throws IOException
        • 지정한 하나의 클라이언트에게 메세지 전송
      • int getClientNumber(CommClientManager cm)
        • 클라이언트 번호 얻기
  • yhg.comm.client
    • ICommClientEvent
      • void onReceiveMessage(Message msg)
        • 클라이언트가 서버로부터 메세지를 받았을 경우 이벤트
      • void onSendMessage(Message msg)
        • 클라이언트가 서버로 메세지를 전송할 경우 이벤트
    • CommClient
      • CommClient(String address, int port) throws UnknownHostException, IOException
      • void send(Message msg) throws IOException
        • 서버로 메세지 전송
      • void setClientEvent(ICommClientEvent evt)
        • 이벤트 설정
      • Socket getSocket()
        • 서버 소켓 얻기

메세지를 추가할 경우 Message의 stataic변수를 만들면됩니다.
그리고 상속받는 Message클래스의 생성자에서 타입을 지정해야 합니다.

public으로 사용할수 있는 메소드등을 정리한 겁니다.

소스파일도 같이 올립니다.

Posted by 초프(초보 프로그래머)
Project2010.03.09 19:09

스레드가 어려움
몇시간을 해도 통신이 잘 안됨
등등

프로젝트를 진행하면서 이런 문제점이 생길거 같아서 미리 이클래스를 작성 하였습니다.

현재로도 하나의 테스트 프로그램만을 작성해 보았으므로

다른 프로그램에서는 어떻게 동작할지는 예상할 수 없습니다 ^^;;

작성해본 간단한 채팅 프로그램의 서버와 클라이언트 입니다.

이것만 보셔도 대충 이해가 가실거라고 생각 됩니다.

--- Server ---

package yhg.comm.test;

import java.io.IOException;

import yhg.comm.message.MSGChat;
import yhg.comm.message.MSGEnterClient;
import yhg.comm.message.MSGLeaveClient;
import yhg.comm.message.Message;
import yhg.comm.server.CommClientManager;
import yhg.comm.server.CommServer;
import yhg.comm.server.ICommClientManagerEvent;
import yhg.comm.server.ICommServerEvent;

public class ChatServer {
	public static void main(String[] args){
		try {
			final CommServer server = new CommServer(1000);
			
			server.setClientManagerEvent(new ICommClientManagerEvent(){
				public void onReceiveMessage(CommClientManager cm, Message msg) {
					int sender = server.getClientNumber(cm);
					MSGChat content = (MSGChat)msg;
					
					System.out.println("["+cm.getSocket().getLocalAddress().toString()+"] receive Message : "+msg);
					
					switch(msg.getType()){
						case Message.type_MSGChat:
							MSGChat chat = new MSGChat();
							chat.setMessage("["+sender+"] "+content.getMessage());
							
							try {
								server.sendAll(sender, chat);
							} catch (IOException e) {
								e.printStackTrace();
							}
							break;
					}
				}
				
				public void onSendMessage(CommClientManager cm, Message msg) {
					
				}
			});
			server.setServerEvent(new ICommServerEvent(){
				public void onEnterClient(CommClientManager cm) {
					int newClient = server.getClientNumber(cm);
					MSGEnterClient ent = new MSGEnterClient();
					ent.setNumber(newClient);
					
					try {
						server.sendAll(newClient, ent);
						System.out.println("["+cm.getLocalAddress().toString()+"] Connect");
					} catch (IOException e) {
						e.printStackTrace();
					}
				}

				public void onLeaveClient(CommClientManager cm) {
					int clientNum = server.getClientNumber(cm);
					MSGLeaveClient ent = new MSGLeaveClient();
					ent.setNumber(clientNum);
					
					try {
						server.sendAll(clientNum, ent);
						System.out.println("["+cm.getLocalAddress().toString()+"] Disconnect");
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			});
			
			server.start();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

--- Client ---

package yhg.comm.test;

import java.io.IOException;
import java.net.UnknownHostException;
import java.util.NoSuchElementException;
import java.util.Scanner;

import yhg.comm.client.CommClient;
import yhg.comm.client.ICommClientEvent;
import yhg.comm.message.MSGChat;
import yhg.comm.message.MSGEnterClient;
import yhg.comm.message.MSGLeaveClient;
import yhg.comm.message.Message;

public class ChatClient {
	public static void main(String[] args){
		try {
			CommClient client = new CommClient("127.0.0.1",1000);
			client.setClientEvent(new ICommClientEvent(){
				public void onReceiveMessage(Message msg) {
					try{
						switch(msg.getType()){
							case Message.type_MSGEnterClient:
								MSGEnterClient enterMsg = (MSGEnterClient)msg;
								System.out.println("-- "+enterMsg.getNumber()+" 님이 입장 하였습니다 --");
								break;
							case Message.type_MSGLeaveClient:
								MSGLeaveClient leaveMsg = (MSGLeaveClient)msg;
								System.out.println("-- "+leaveMsg.getNumber()+" 님이 퇴장 하였습니다 --");
							case Message.type_MSGChat:
								MSGChat chat = (MSGChat)msg;
								System.out.println(chat.getMessage());
								break;
						}
					} catch(ClassCastException e){}
				}

				public void onSendMessage(Message msg) {
					
				}
			});
			client.start();
			
			Scanner scanner = new Scanner(System.in);
			
			while(true){
				String input = scanner.next();
				
				if(!input.equals("")){
					MSGChat chat = new MSGChat();
					chat.setMessage(input);
					client.send(chat);
				}
			}
		} catch (UnknownHostException e) {
		} catch (IOException e) {
		} catch (NoSuchElementException e){
		}
	}
}

문제점이 있으시면 바로바로 알려주세요~

Posted by 초프(초보 프로그래머)
Project2010.03.09 18:59

팀프로젝트를 미리 준비하면서 만들어 본 통신 클래스...;

복잡했던 스레드 이런걸 단방에 해결해 주도록 만들었습니다.

1:n의 통신이 가능하게 하였으며... 중요 클래스를 건드리지 않고

이벤트를 작성하는 형식으로 만들어 보았습니다.

아직 부족한게 많고 허접할거 같지만... 


일단 처음으로 통신과정 중에 왔다 갔다할 객체를 메세지라고 하여 만들었습니다.

그리고 그 메세지 클래스를 상속받아서 구체적인 메세지들이 구현이 됩니다.

--- Message.Java ---

package yhg.comm.message;

import java.io.Serializable;

/**
 * 통신 중에 주고 받는 메세지
 * 
 * @author	Yoon HyunGook
 * @since	2010-03-08
 */
public class Message implements Serializable {
	private static final long serialVersionUID = 5795268628773097426L;
	private int number;
	private int type;

	/**
	 * 미리 정해진 메세지 타입
	 * 필요시에 추가 하면됨
	 */
	public final static int type_MSGTable = 1;
	public final static int type_MSGBoolean = 2;
	public final static int type_MSGChat = 3;
	public final static int type_MSGEnterClient = 4;
	public final static int type_MSGLeaveClient = 5;
	
	/**
	 * 생성자
	 * 
	 * @author	Yoon HyunGook
	 * @since	2010-03-08
	 */
	public Message(){
		type = 0;
	}
	
	/**
	 * 메세지 타입 설정
	 * 
	 * @author	Yoon HyunGook
	 * @since	2010-03-08
	 * 
	 * @param	메세지 타입
	 */
	protected void setType(int type){
		this.type = type;
	}
	
	/**
	 * 메세지 타입 얻기
	 * 
	 * @author	Yoon HyunGook
	 * @since	2010-03-08
	 * 
	 * @return	메세지 타입
	 */
	public int getType(){
		return type;
	}
	
	/**
	 * 클라이언트 번호 얻기
	 * 
	 * @author	Yoon HyunGook
	 * @since	2010-03-08
	 * 
	 * @return	클라이언트 번호
	 */
	public int getNumber(){
		return number;
	}
	
	/**
	 * 클라이언트 번호 설정
	 * 
	 * @author	Yoon HyunGook
	 * @since	2010-03-08
	 * 
	 * @param	클라이언트 번호
	 */
	public void setNumber(int num){
		this.number = num;
	}
	
	/**
	 * 객체 출력
	 * 
	 * @author	Yoon HyunGook
	 * @since	2010-03-08
	 * 
	 * @return	String
	 */
	public String toString(){
		return Integer.toString(getNumber());
	}
}


--- MSGChat.java ---
package yhg.comm.message;

/**
 * 채팅 메세지
 * 
 * @author	Yoon HyunGook
 * @since	2010-03-08
 */
public class MSGChat extends Message{
	private static final long serialVersionUID = 6997142338486570285L;
	private String message;
	
	/**
	 * 생성자
	 * 
	 * @author	Yoon HyunGook
	 * @since	2010-03-08
	 */
	public MSGChat(){
		setType(Message.type_MSGChat);
	}
	
	/**
	 * 전송 내용 설정
	 * 
	 * @author	Yoon HyunGook
	 * @since	2010-03-08
	 * 
	 * @param	전송 내용
	 */
	public void setMessage(String str){
		message = new String(str);
	}
	
	/**
	 * 전송 내용 얻기
	 * 
	 * @author	Yoon HyunGook
	 * @since	2010-03-08
	 * 
	 * @return	전송 내용
	 */
	public String getMessage(){
		return message;
	}
	
	/**
	 * 객체 출력
	 * 
	 * @author	Yoon HyunGook
	 * @since	2010-03-08
	 * 
	 * @return	String
	 */
	public String toString(){
		return getMessage();
	}
}


메세지 타입은 새로운 메세지가 생길때 마다 수동적으로 추가 해줘야 합니다.

type : 메세지의 종류를 구분
number : 클라이언트의 번호 (필요시만 사용)
Posted by 초프(초보 프로그래머)
Programming/Android2010.02.01 14:55
http 프로토콜을 이용하여 통신을 하는 예제입니다.

주소에 해당되는 문서의 내용을 받아옵니다. 

여기서는 그냥 일반 html 문서서를 가져 오도록 해보았습니다.  
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class Test extends Activity {
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        TextView text = (TextView)findViewById(R.id.htmlText);
        
        URL url = null;
        
		try {
			url = new URL("http://family7914.cafe24.com");
        	HttpURLConnection http = (HttpURLConnection)url.openConnection();
        	BufferedReader in = new BufferedReader(new InputStreamReader(http.getInputStream()));
        	StringBuffer buffer = new StringBuffer();
        	
        	int c;
        	
        	while((c=in.read()) != -1){
        		buffer.append((char)c);
        	}
        	
        	text.setText(buffer);
        	
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
    }
}

 

코드를 실행해보면 위와 같은 결과가 나옵니다.

만약 결과가 나오지 않거나 오류가 발생한다면... 
처음으로 생각해 볼수 있는 것이 Manifest의 Permission 입니다. 
이건 우리가 어떤 기능을 사용할 것이다 라고 미리 알려주는 것입니다. 
그래야만 사용할 수 있거든요~
두번째는 제가 어리석어서 생긴 경우인데...
실행을 할 경우 문서의 용량이 크면 로딩이 길게 되어있습니다. 
그리고 그전에 디버깅을 위한 메세지가 뜨는데 그것을 그냥 오류로 생각해 버리는겁니다.
그러므로 메세지를 잘 확인하세요~ ^^;
Posted by 초프(초보 프로그래머)
Programming/JAVA2009.10.13 00:34

ABC.java


Test.java


- Output -


list를 정렬하는 방법을 찾다가 찾은 방법입니다. CompareTo Method를 이용해서 두 객체의 비교가 일어납니다.

modified mergesort 가 이용되고 stable이 유지되며 O(n^2) 은 피하며 nlog(n)이 보장된다고 합니다.
Posted by 초프(초보 프로그래머)
Programming/JAVA2009.10.13 00:11

 Test.java


ABC.java

- Output -

직접 제작한 클래스의 복사가 가능한 Clone Method를 제작하는 방법 입니다.

clone() Method를 저렇게만 구현하면 기본적인 동작이 가능합니다.
Posted by 초프(초보 프로그래머)
Programming/JAVA2009.05.25 16:39

str_pad는 문자열을 지정한 만큼의 길이가 안되면 지정한 문자로 채우는 것입니다.

$number = 123;
$str = str_pad($number,5,"0",STR_PAD_LEFT) // "00123"


자바에서는 다음과 같이 하면된다.

int number = 123;
String str = String.format("%05d",number); // "00123"

Posted by 초프(초보 프로그래머)
Programming/JAVA2009.03.30 11:38

 조금 헷갈리던 UpCasting 과 DownCasting 이 이제야 이해가 되고 있네요;


위와 같이 Class가 있다고 하면..

Animal ani_1 = new Dog();
Animal ani_2 = new Cat();
Animal ani_3 = new Bird();


ani_1.move();
ani_1.run(); 
  // 오류 발생

ani_2.sleep();  // Cat 의 sleep() 실행
ani_2.run();  // 오류 발생

ani_3.move();  // Bird의 move() 실행
ani_3.sleep();
ani_3.fly(); 
  // 오류 발생

UpCasting을 하게되면 Animal class의 Memory 크기에 Dog, Cat, Bird의 Memory를 넣게 된다

그래서 UpCasting된 ani_1, ani_2, ani_3 는 Animal의 메모리 만큼을 가지고 Animal의 Method만을 호출할 수 있다.

만약 하위 Class 인 Dog, Cat, Bird 에서 상위 Class Animal 의 Method를 Overriding 해주었을 경우 하위 Class의 Method가 실행된다.

DownCasting 은 UpCasting 된것을 원래의 type으로 돌리는 것이다.

Dog dog = (Dog)ani_1;

이와 같이 ani_1의 Animal Object 를 (Dog) 로 DownCasting 해주므로써 dog에 원래대로 들어가게 된다.

UpCasting하기전 DataType과 DownCasting 할려는 DataType은 꼭!!!! 같아야 한다. 안그러면 오류 발생!!!!
Posted by 초프(초보 프로그래머)
Programming/JAVA2009.03.24 16:10

배열 참조

 C에서 배열의 이름이 그 배열의 포인터를 가르키는 것과 같이 Java에는 배열의 이름이 참조값을 가진다.
그러므로 다음과 같이 사용하면 두개의 변수로 하나의 배열을 다룰수 있다.

int[] num = {1,2,3,4,5};
int[] num_1 = num;
int[] num_2 = num_1;


위의 세 변수 num, num_1, num_2는 모두 같은 참조값을 가지고 있기 때문에 하나의 배열이라고 볼수 있다.
만약 하나의 변수이름으로 값을 수정하게 되면 3개의 값이 다 바뀌는것 같을 것이다.

num_2[0] = 9;
for(i=0;i<num.length;i++)
     System.out.println("num["+i+"] : "+num[i]+"\tnum_1["+i+"] : "+num_1[i]+"\tnum_2["+i+"] : "+num_2[i]);


위의 결과는 다음과 같다.

num[0] : 9     num_1[0] : 9     num_2[0] : 9
num[1] : 2     num_1[1] : 2     num_2[1] : 2
num[2] : 3     num_1[2] : 3     num_2[2] : 3
num[3] : 4     num_1[3] : 4     num_2[3] : 4
num[4] : 5     num_1[4] : 5     num_2[4] : 5


3개의 변수는 하나의 배열 참조값을 공유하고 있는것이다. 이것이 참조이며 반드시 데이터형은 같아야 한다.

public void copy(int[] A, int[] B)
{
     for(int i=0;i<A.length;i++)
          B[i] = A[i];
}


A와 B 모두 참조값을 받는다. 그러므로 A와 B를 변경하면 매개변수로 넘긴 배열도 변경된다. C언어 에서는 포인터를 사용해야할 이런일이 아주 쉽게 된다.

2차원 배열 선언

1차원 배열 선언과 거의 같다.

int[][] num = new int[2][3];
int[][] num_1 = new int[2][3] {{1,2,3}, {4,5,6}, {7,8,9}};
int[][] num_2 = {{1,2,3}, {4,5,6}, {7,8,9}};

Posted by 초프(초보 프로그래머)