1 / 33

Java Network Program

Java Network Program. 16. Java Network. Server-Client 구성도. 16. Java Network. Server-Client 구현 Server – Java Application Client – Java Swing Applet 으로 만들 때의 고려 사항 - 애플릿 바이트 코드가 있는 호스트 이외의 호스트와의 접속 금지 - 애플릿과 접속할 소켓서버는 애플릿이 위치한 웹서버와 같은 호스트에서 실행되어져야 함 . - 보안 정책 파일 편집.

gerda
Download Presentation

Java Network Program

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Java Network Program

  2. 16. Java Network • Server-Client 구성도

  3. 16. Java Network • Server-Client 구현 • Server – Java Application • Client – Java Swing • Applet으로 만들 때의 고려 사항 - 애플릿 바이트 코드가 있는 호스트 이외의 호스트와의 접속 금지 - 애플릿과 접속할 소켓서버는 애플릿이 위치한 웹서버와 같은 호스트에서 실행되어져야 함. - 보안 정책 파일 편집

  4. 16. Java Network • Server and Client • 프로그램 작동 순서 1) 서버가 소켓을 생성하고 연결을 기다린다.  2) 클라이언트에서 서버의 소켓에 연결한다.  3) 클라이언트에서 데이터를 전송한다.  4) 서버에서 데이터를 받아서 화면에 출력한다.  5) 서버와 클라이언트의 소켓 연결을 끊는다. 

  5. 16. Java Network • ServerSocket 1)통신을위해서는먼저서버에서소켓을준비. - 자바에서는그것을위해ServerSocket이라는클래스가제공. -이것은java.net패키지에들어 있음. ServerSocket소켓변수이름=newServerSocket(포트번호); ex) ServerSocketsrvSocket=newServerSocket(5777); - 다음은이서버소켓을사용하여클라이언트와통신할다른소켓 을만들어 주어야 함. -서버쪽에서는반드시두개의소켓이필요. ; 하나는서버용소켓인데단지클라이언트의연결을기다림. ; 따라서클라이언트와연결이되면실제로통신을하기위해서 소켓을하나더만들어서연결해주어야함.

  6. 16. Java Network • ServerSocket ; 이소켓은서버소켓.accept()명령으로만들어줄수있음. Socketsoc=srvSocket.accept(); ; 여기서srvSocket은서버소켓의이름. ; 클라이언트에서도이소켓을사용하여연결. - 다음은입력을위한스트림을선언해야 함. ; 만들어놓은소켓에서스트림을얻어와야함. (Socket에서 (Input)OutputStream을 얻을 수 있음) ; 스트림은java.io패키지에포함되어있음. InputStreamis=soc.getInputStream(); - is는스트림변수이름,soc는선언한소켓의이름.

  7. 16. Java Network • ServerSocket - 다음은 이스트림에서입력을받기위해이스트림을읽을수 있는Reader를정의해야 함. InputStreamReaderisr=newInputStreamReader(is); ; is는앞에서선언한inputstream이고, isr은InputStreamReader의이름. ▶ 서버쪽소켓준비완료. ; 데이터를읽기위해서InputStreamReader에있는read() 메소드를사용. 즉,inta=isr.read();와같이하면a에한글자가입력. ; int값으로넘어오는데,문자로바꾸기위해서는형변환 필요. chara=(char)isr.read(); ; 들어오는문자들을하나의문자열에저장하기위해서는 str=str+(char)isr.read();와같이문자열에더해주면됨.

  8. 16. Java Network • 정 리 (Server 측) 1) ServerSocket 생성 2) Client와 접속(통신용 Socket 생성 및 port 할당) 3) Socket에서 InputStream 획득 4) 데이터 read Client 측 ▶ Client Socket에서 획득한 OutputStream을 이용하여 데이터를 write

  9. 16. Java Network • Socket(Client) 2)클라이언트소켓은서버소켓보다비교적 간결. ; 서버소켓은필요가없고,InputStream을OutputStream으로, InputStreamReader를OutputStreamWriter로바꾸면됩. - 먼저소켓 생성. - 앞에서생성한서버의IP와port번호를알고있어야함. Socketsoc=newSocket("127.0.0.1",5777); ; 여기서"127.0.0.1"은IP주소. ; soc는소켓의이름으로변수로쓸수있는것을적어주면됨. ; 여기서Socket과동일한클래스를사용.

  10. 16. Java Network • Socket (Client) - 다음은이소켓에서스트림을생성하여야 함. - 서버로데이터를보내는위해OutputStream을사용. OutputStreamos=soc.getOutputStream(); - 다음은앞에서와같이OutputStreamWriter를만들어 줘야함. OutputStreamWriterosw=newOutputStreamWriter(os); ; 이렇게하면writer까지만들어 졌음. ; 데이터를전송하기위해서는write()메소드사용. ▶ 클라이언트쪽소켓준비완료.

  11. 16. Java Network • 정 리 (Client 측) 1) Socket 생성 2) (Server)Socket과 접속(IP 주소, port) 3) Socket에서 OutputStream 획득 4) 데이터 write Server 측 ▶ ServerSocket에서 획득한 InputStream을 이용하여 데이터를 read

  12. 16. Java Network • 실질적인 데이터 입출력(read) 3)클래스에구현된메소드(read,write)를사용해서read,write. ; InputStreamReader intread(); voidread(char[]chr,intoffset,intlength); - 앞의것은한글자를읽음. ; 즉,a=isr.read();라고하면a에는한글자만들어가있다는뜻. ; 단, a는정수형(int)이어야함. ; 문자로바꾸기위해서는형변환(typecasting)을해주어야함. - 뒤의것은몇번째글자(offset)부터몇글자(length)를얻어와서 char의배열에넣는다는의미.

  13. 16. Java Network • 실질적인 데이터 입출력(read) publicstaticvoidmain(Stringargs[]){ InputStreamReaderisr=newInputStreamReader(newServerSocket (5777).accept().getInputStream()); Stringstr=""; for(inti=0;i<10;i++){str="str+(char)isr.read();"} System.out.println(str);isr.close();} - InputStreamReader를만들기위해ServerSocket을만들고그것의 accept()메소드를이용해서Socket을만들고다시InputStream을 만드는모든과정. - str을String으로선언해주고for문으로열개의문자를읽어와서str 에더해주고서다시str을출력하는프로그램. - 이코드는실행되지않음(exception 처리가 필요함)

  14. 16. Java Network • 실질적인 데이터 입출력(write) publicstaticvoidmain(Stringargs[]){ OutputStreamWriterosw=new OutputStreamWriter(newSocket("127.0.0.1",5777).getOutputStream()); Stringstr="0123456789"; osw.write(str,0,10); osw.flush(); osw.close(); } - OutputStreamWriter클래스에는write()가여러개로정의되어있음. - str의0번째글자부터10개의글자를전송하라는의미. - osw.flush();는글자를실제로전송하라는의미. ; 이것을써주지않으면메시지를받는쪽에서실제로읽을수가없음.

  15. 16. Java Network • 예외 처리 -소켓프로그램(SocketServer.javaSocketClient.java)에서 예외상황을발생시킬수있는메소드는두가지가있음. 첫째는, 소켓을만들때,앞에서소켓을만들수없다는예외상황. 둘째는, 데이터를입력 받거나출력할 때중간에소켓이끊겼거나하는 상황에서발생. -따라서SocketServer.java/SocketClient.java에서는 각각최소한두가지씩의예외처리를해주어야함.

  16. 16. Java Network • Socket publicstaticvoidmain(Stringargs[]){ try{                …… }catch(IOExceptione){                …… } } - IOException은여러가지예외상황 중IO(Input/Output)에 관계된예외상황을잡아내라는의미(스트림)

  17. 채팅 프로그램(Server) import java.io.*; //입출력 처리 import java.net.*; //네트워크 처리(socket 사용을 위해) import java.util.*; //Vector Class 사용 //Thread Class는 Object Class의 하위 Class 이므로 묵시적 처리 class ChatServer { //chatters가 접속하면 instance가 자동으로 생성 //port를 통해 Client와 연결되어 있음 //Client가 메시지를 보내면 Server Class의 Socket에 전달되고 이를 //기다리던 Thread는 데이터를 읽어서 다른 Chatters에게 메시지 전달 Vector chatters; //가변길이의 배열(접속자를 가변적으로 처리하기 위함) public ChatServer(int port) throws Exception { //ChatServer 생성자 ServerSocket ss = new ServerSocket(port); //서버소켓 생성(클라이언트의 접속 경로) //클라이언트는 서버소켓으로 접속을 시도함(실질적 접속통로는 아님) chatters = new Vector(5); //묵시적으로 5개의 요소를 가진 Vector 객체 생성 //chatters에 메시지를 broadcast해야 할 소켓들을 저장 //Client마다 별도의 스레드로 이루어 짐.

  18. 채팅 프로그램(Server) while(true) { // 주어진 조건이 성립되면 {} 수행 , 즉 true이므로 무한 //루프 발생, 서버 프로그램을 계속 수행함을 의미 Socket man = ss.accept(); // 클라이언트의 접속을 기다림 // 클라이언트가 접속할 때까지 프로그램이 멈춘(block)상태임 // 클라이언트를 처리할 스레드를 생성하고 벡터 클래스에 추가 System.out.println("Accepted from " + man.getInetAddress()); // 접속이 되면 표준 출력문(out, err) 수행 MesgSender c = new MesgSender(this, man); // 접속이 되면 MesgSender Thread를 생성하고, // 이때 Socket 인자를 넘겨줌) chatters.addElement(c); // 객체를 추가 하기 위함(접속 client) c.start(); // 생성된 Thread를 구동 시킴(병행 실행) } } publicstaticvoid main(String a[]) throws Exception { // main 메소드 new ChatServer(7788); //서버는 7788번 port를 열고 Client를 기다림 // 접속이 되면 7788포트를사용하는ChatServer객체를생성한다. }

  19. 채팅 프로그램(Server) class MesgSender extends Thread { // MesgSender 클래스 정의 // 서버 스레드는 직접 구현해 주어야 함 // 클라이언트에 연결된 소켓을 넘겨 받았으므로 이 소켓에서 // 스트림을 만들어 reader와 writer를 만들어 주어야 함 Socket s; //각MesgSender객체가하는일은담당클라이언트로부터 // 문자열을전송 받고, 전송 받은문자열을접속된모든 // 클라이언트에게broadcast하는일. DataInputStream r; DataOutputStream w; ChatServer server; public MesgSender(ChatServer cs, Socket s) throws Exception { // MesgSender 생성자 //생성자의인자로ChatServer객체와소켓객체를사용. //생성자의인자로ChatServer객체를사용하는이유는ChatServer에서 // 선언된 벡터chatters에접근해야하고,하나의클라이언트로부터 // 전송 받은메시지를모든 클라이언트에게broadcasting할때 // chatters객체를사용해야하기때문.

  20. 채팅 프로그램(Server) server = cs; this.s = s; r = new DataInputStream(s.getInputStream()); //소켓으로부터 입력스트림 획득 w = new DataOutputStream(s.getOutputStream()); //소켓으로부터 출력스트림 획득 } publicvoid run() { // run() 메소드 overriding // 소켓에서 데이터를 받는다.(run() 메소드가 끝나면 스레드는 종료됨) //MesgSender객체가실행할내용이정의되어있다. //최초전송되는문자열을이름이라가정,전송받은이름을 broadcast. // 다음은무한루프로서전송받은문자열을broadcast. try { String msg; // String 객체 선언 String name = r.readUTF(); // 데이터 입력스트림에서 수정된 UTF-8 형식을 사용하여 // 인코드된 문자열로 읽음. // DataInputStream으로부터 데이터를 읽어 name에 저장 broadcast(name + " joined"); // 스트림을 읽어서 broadcast로 메시지 전달

  21. 채팅 프로그램(Server) while(true) { // run() 메소드는 무한루프를 돌아야 함. 연결상태에서 지속적으로 // 데이터를 주고 받아야 함. 클라이언트에 접속되어 있는 한 // 스레드는 유지 됨 msg = r.readUTF(); // DataInputStream 을 얻어와 데이터를 읽음 broadcast(name+" : "+msg); // 읽은 데이터를 broadcast 함. } } catch(IOException excep) {} finally { server.chatters.removeElement(this); //객체 목록에서 삭제 } } void broadcast(String mesg) throws IOException { //broadcast 메소드 정의 synchronized(server.chatters) { //하나의 스레드만 접근 가능함. //여러스레드가동시에chatters에접근하는것을방지하기위함.

  22. 채팅 프로그램(Server) Enumeration e = server.chatters.elements(); //Enumeration은 열거형 원소들을 처리하기 위한 시스템 인터페이스 //Enumeration객체로선언하는이유는hasMoreElement() 메소드와 //nextElemnt()메소드를사용할수있어서배열처리가단순하기때문. //두개의 추상메소드를 반드시 구현해야 함 //hasMoreElements() : 원소가 남아있으면 true, 아니면 false 반환 //nextElement() : 나열된 순서에 따라 다음 객체를 반환 //ChatServer객체의chatters에저장된소켓들은Enumeration객체로선언. MesgSender ms; while(e.hasMoreElements()) { //조건이 성립하면 {} 수행 //chatters에지정된모든소켓에메시지를전송한다. ms = (MesgSender) e.nextElement(); // (MesgSender)은 형변환을 의미 ms.w.writeUTF(mesg); //기계에 독립적인 방법으로 UTF-8 인코딩을 사용하여 문자열을 //기본 출력 스트림에 기록함. ms.w.flush(); } } } } } //실제 전송

  23. 채팅 프로그램(Server) MesgSender ms; ms = (MesgSender) e.nextElement(); 클래스의상속과관계된형변환.Thread클래스를상속하여MesgSender를작성 하였음.자바의모든클래스는Object라는클래스에서파생.Thread또한마찬가지 이고,따라서MesgSender또한Object로부터파생된것(Object를상속한것). SuperClass와SubClass가있을때,SuperClass를상속하여SubClass를만들었다면. SuperClass로선언된변수는SubClass를받을수있다.다음코드는컴파일이 가능. Superclasss1=newSuperclass(); // print(); Subclasss2=newSubclass(); print(); s1=s2; 하지만,subclasss2가s1에넣어지면,s2가새로만든메소드는사용할수없게됨. 즉,print()라는메소드가s2에만있고,s1에는없다면s1=s2이므로s1에는s2가들어 있지만,s1.print()와같이사용할수없음.따라서print()메소드를사용하기위해서는 s1을다시s2로형변환(typecasting)을해주어야함. ((s2)s1).print()는가능 함. 이런이유로형변환이필요.위에있는Vector클래스의메소드들을보면알수있지만, addElement(Objectobj)와같이컴포넌트를추가할때Object로받게됨. 즉벡터안에서는Object클래스로변환되어저장되어짐.elementAt()도역시Object로 반환 함.Object클래스에는sendMessage()라는메소드가없음.따라서반환된 클래스를다시처음대로MesgSender로만들어주기위해서는형변환이 필요함.

  24. MesgSender ms; // Thread class => Object class 에서 상속 Enumeration e; // Object class 에서 상속 ms = e; // 할당 가능, 그러나 ms는 e의 메소드 사용 불가 때문에 nextElement(); 가 Enumeration에 있으므로 ms = e.nextElement(); 는 접근 불가, 때문에 접근을 위해 형변환 필요 ms = (MesgSender) e.nextElement(); //형변환하여 접근 가능

  25. 채팅 프로그램(Client) import java.io.*; import java.net.*; import java.awt.*; // java swing으로 구현하더라도 awt는 선언되어야 함. // java.awt.Component의 하위 class 임 import java.awt.event.*; //이벤트 처리 import javax.swing.*; //java swing으로 구현 class ChatFrame extends JFrame implements // ChatFrame 클래스 정의 // JFrame 상속, JFrame 은 swing의 최상위 class 임 Runnable, ActionListener { // Thread Class, 이벤트를 위한 리스너 포함 //ChatFrame객체는사용자로부터문자열을입력 받아전송하는일과 //서버로부터 문자열을전송 받아텍스트영역에출력해야하므로 //멀티스레딩이필수적. //텍스트필드에문자열을입력받아전송하는작업은사용자입력에따른 //것이므로이벤트처리. //서버로부터문자열을전송받아출력하는작업은항시발생하므로run() //메소드에서 무한루프로처리.

  26. 채팅 프로그램(Client) DataInputStream r; DataOutputStream w; JTextField mesg = new JTextField("Key in Name First"); JTextArea output= new JTextArea(); boolean connected = false; // 서버와의 연결 상태를 나타냄. String host; Thread th; //스레드 생성 ChatFrame(String host) { //생성자, 서버의 host가 넘어 옴. super("Chatting JFrame"); // JFrame에 부착 //스레드 클래스의 생성자를 사용할 수 없으므로 이렇게 작성 함. Container c = getContentPane(); //swing에서의 컴포넌트 부착 방법 //ContentPane은 중량컨테이너에 부착되는 모든 컴포넌트의 접속창 //역할을 함. awt와 달리 swing에서는 중량컨테이너에 layout관리자를 //설정하거나 중량컨테이너에 컴포넌트를 부착하기 위해서는 먼저 //ContentPane을 구하여야 함. //swing에서 중량컨테이너는 awt에서 컨테이너에 해당 함. //교재 517-518 page 참조

  27. 채팅 프로그램 (Client) c.setLayout(new BorderLayout()); // ContentPane을 구한 후 BorderLayout설정 this.host = host; mesg.addActionListener(this); // 리스너에 등록 c.add(mesg, BorderLayout.SOUTH); //텍스트필드를 하단에 부착 c.add(new JScrollPane(output), BorderLayout.CENTER); // JTextArea 객체를 스크롤 시키려면 JScrollPane(경량컨테이너)을 사용 // JTextArea center 에 부착 setLocation(200, 300); //프레임의 위치 설정 setSize(500, 400); //프레임의 크기 설정 show(); //생성된 프레임은 자동으로 보이지 않으므로 보이게 함. } publicvoid actionPerformed(ActionEvent e) { // 텍스트필드 이벤트 처리 //사용자가처음에이름을입력하고엔터키를치면서버에접속하고 //이름을서버에 전송.스레드th를생성하여run()메소드를실행하도록 함. //그이후에입력되는문자열은단순히서버로전송 함.

  28. 채팅 프로그램 (Client) try { if (connected==false) { //데이터가 입력될때까지 blocking 상태 //통신 링크가 확립이 안된 상태. 초기 입력값이 없는 상태 Socket s = new Socket(host, 7788); //서버에서 사용한 소켓과 port는 동일하게 사용(서버에 접속 시도) r = new DataInputStream(s.getInputStream()); w = new DataOutputStream(s.getOutputStream()); w.writeUTF(mesg.getText()); // Key in Name First을 읽어옴. output.append("Connection Established"); //JTextArea에 String 추가 connected = true; // 통신 링크 확립, 데이터를 broadcast. mesg.setText(""); // 텍스트필드의 내용을 지움. th = new Thread(this); th.start(); } //스레드 구동 else { w.writeUTF(mesg.getText()); mesg.setText(""); } } catch(IOException ex) {} } // 예외가 발생하더라도 close() 메소드를 // 이용하여 종료되도록 처리해 주는 것이 좋음.

  29. 채팅 프로그램(Client) publicvoid run() { // run() 메소드 정의(overriding) // 소켓으로부터문자열을읽어텍스트영역에출력하는일을한다. try { while(true) { // 무한루프 output.append("\n"+ r.readUTF()); // 읽어온 데이터를 JTextArea에 // 출력 } } catch(Exception e) {} // 예외가 발생하더라도 close() 메소드를 // 이용하여 종료되도록 처리해 주는 것이 좋음 } publicstaticvoid main(String args[]) throws Exception { ChatFrame f; if(args.length==1) // 명령행인자가 있으면 IP주소로 사용 { f = new ChatFrame(args[0]); } else { f = new ChatFrame("127.0.0.1"); }

  30. 채팅 프로그램(Client) f.addWindowListener( // 리스너 등록(종료버튼 클릭 처리) new WindowAdapter() { //Adapter 사용(필요한 메소드만 overriding) //이벤트처리를 위해 WindowAdapter 객체를 등록 publicvoid windowClosing( WindowEvent e ) { // 이벤트 발생에 따른 메소드 처리 // WindowAdapter 에서 반드시 정의되는 메소드 // windowClosing() 메소드는 프레임 객체의 종료버튼을 클릭했을 때 // 호출되는 메소드임. System.exit( 0 ); // 종료 } } ); } }

More Related