반응형
class 파일을 java 파일로 볼수있는 볼 수 있습니다.
반응형
반응형

자바의 TCP 네트워크는 java.net 클래스 에서 지원해주는 ServerSocket클래스, Socket 클래스의 상호 연결로 이루어 지는 네트워크이다. 자바의 네트워크에는 이외에도 UDP라는 네트워크가 있다

TCP와 UDP
TCP는 연결형으로 전화기 처럼 송신자와 수신자를 연결한뒤 안전하게 정보를 주고 받는 방식이다. 이는 유일한 경로를 이용하게 됨으로 신뢰성이 보장된다. 이는 중요한 통신이 필요할때 주로 이용한다. 이는 유일한 경로로 연결이 끊킬때 까지 패킷을 주고 받을수 있다.

UDP는 비연결형으로 영화나 음악같은 파일을 주고 받을때 사용된다. 이는 패킷하나하나를 보낼 때마다 각각의 패킷에 목적지 주소를 반드시 가져야한다. 상대 컴퓨터의 상태를 점검하기위해 사용하는 PING이 적당한 예이다.

소캣(Socket)
소캣은 상호 연결된 응용프로그램들 사이의 안정된 정보 교환을 제공하고 있는 매체라 할 수 있다.

포트(Port)
컴퓨터들은 하나의 통신선을 이용하지만 논리적은 개념으로 그 통로를 나누어 여러개의 통신 프로그램을 동시에 사용 할 수 있다. 그 통로를 포트라고 한다.

TCP 네트워크 방식의 연결
위에서 말한 것처럼 TCP 네트워크는 상호 연결로 이루어진다. 즉, 한번 연결하면 연결을 어느 한쪽이 끝날때까지 계속해서 패킷 정보를 주고 받을 수 있다. 이것은 ServerSocket 클래스와 Socket 클래스로 이루어진다. Socket 클래스는 앞서 말했다 싶이 정보교환을 제공하는 매체가 되는 객체인데. 두컴퓨터의 소켓과 소켓을 통로로 연결하여 통신을 할수 있겠금 해준다. 
ServerSocket은 서버측에서 대기를 하다가 클라이언트쪽의 요청이 도착하게되면 자신의 소켓을 반환하여 준다.
클라이언트에서 서버측으로 Socket을 이용하여 요청을 보내기 위해서는 서버측의 IP와 포트 번호가 필요하다. 그래서 Socket
객체를 선언 생성 할때는 임의로 IP와 포트번호를 적어준다. 하지만 서버는 어떻게 상대편의 IP를 알고 포트번호를 알수 있을까? 간단하게 생각해보니 알수 있었다. 클라이언트쪽에서 요청을 보낼시에 자신의 IP와 포트정보를 포함해서 보내면 서버측에서 이를 받아 생성할때 그정보를 자신의 소켓에 저장하는 것이다. 이로써 둘은 서로의 IP와 포트 정보를 알게되고 그  ServerSocket이 닫히게되면 그 서로의 소켓 연결은 끝나게 된다. 

이를 그림으로 알아보겠다.

후우 디자인이 정말 안습하지만 설명하겟다.  

일단은 Server가 되는 컴퓨터와 Client가 되는 컴퓨터가 있어야 하기 때문에 서버가 되는 컴퓨터에 ServerSocket이 생성되어 있어야 한다. 그 ServerSocket에 .accept()메소드를 이용하여 Client에서 서버로 요청이 올때까지 대기시켜 놓는다. 요청이 오게되면 상대방의 IP와 포트 정보를 가지는 Socket을 생성하여 두 소켓을 연결상태로 유지한다.
생성된 Socket 객체의 InputStream과 OutputStream을 이용하여 요청과 응답을 방복하며 계속 정보를 주고 받을 수 있다.
그리고 모든 정보를 주고 받고 나면 Socket과 ServerSocket을 .Close()하여 종료 시키면 모든 작업이 끝난다.

간단한 소스를 보겠다.

Server
class Server extends JFrame{

 try{
 serversocket= new ServerSocket(9001); //서버 소캣 생성시 들어올 포트를 지정해준다.
 System.out.println("소캣생성완료 대기중");
 socket= serversocket.accept();
 System.out.println("대기후소캣생성");
//BufferedReader은 요청온 정보가 바이트 스트림이 때문에 이를 문자열스트림으로 바꾼다.
 reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// PrintWriter또한 문자열로 바꿔준다.
 writer =new PrintWriter(socket.getOutputStream(),true);
 System.out.println("버퍼 생성완료");
 
 while((mng=reader.readLine())!=null){ // 요청온 정보가 있게되면 응답을 보낸다.
  System.out.println(mng);
  System.out.println("출력");
  str="서버철님이시다.";
  writer.println(str);// 보낼때에는 꼭 println으로 보내야 한다. 상대방이 라인으로 검사하기 때문이다.
  System.out.println("메세지 전송");
 }
 
 }catch(Exception e){
  e.getStackTrace();
 }finally{
   try{
   if(socket!=null)socket.close();
   if(reader!=null)reader.close();
   if(writer!=null)writer.close();
   }catch(IOException e){
    e.getStackTrace();
   }
  }
 
 String mng="";
 ServerSocket serversocket=null;//서버소켓선언
 String str =null;
 PrintWriter writer=null;
 BufferedReader reader=null;
 Socket socket=null;// 소켓선언
 Board bod= new Board(20,30);
}

Client
class Client extends JFrame{
  try{
   socket= new Socket("127.0.0.1",9001);// 서버측의 주소와 포트 번호를 지정해준다.
   System.out.println("소캣생성완료");
   reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
   writer =new PrintWriter(socket.getOutputStream(),true);
   System.out.println("버퍼 생성완료");
   wprint(); // 요청메소드 호출
   
   while((mng=reader.readLine())!=null){
    System.out.println(mng);
    System.out.println("출력");
   }
  }catch(Exception e){
   e.getStackTrace();
  }finally{
   try{
   if(socket!=null)socket.close(); // 소켓 종료
   if(reader!=null)reader.close();
   if(writer!=null)writer.close();
   }catch(IOException e){
    e.getStackTrace();
   }
  }

 
 public void wprint(){
  str="클라이언트철님이시다.";
  writer.println(str);//println로 해야 readLine()으로 읽을 수있다.
  System.out.println("메세지 전송완료");
 }
 String str =null;
 String mng ="";
 PrintWriter writer=null;
 BufferedReader reader=null;
 Socket socket=null;
 Board bod= new Board(20,30);
}

writer.println과 readLine() 부분에서 많이 해메게 되었는데
reader.readLine()하게되면 한 문장을 받아오게 되는데 나는 writer.print()로 메세지를 보냈더니.
한문장으로 인식 하지 못하는거 같다. 그래서 writer.println()으로 했더니 reader.readLine()이 제대로 읽어왔다.
참 쉬운부분인데 바보같다 앞으로는 이런 간단한 부분을 실수 하지않도록 신경 쓰도록 하여야겠다.
반응형
반응형

JAVA네트워크

저희 오목네트워크게임 프로그램은 TCP 소켓 프로그래밍을 이용하여 서버를 구성 하였습니다.
TCP 소켓 네트워크프로그래밍은 연결 요청을 기다리는 서버 프로그램과 연결을 요청하는
클라이언트 프로그램으로 구성되며 클라이언트 프로그램은 연결을 요청하고
서버프로그램은 그 요청을 받아서 연결을 맺고 그 연결을 통해 데이터를 주고 받습니다.

그 구동방법은 이러합니다. 보시는 소스는 서버측 소스입니다. 서버측에서
serversocket 소켓을 생성하여  client측 요청을 받아들인다음 Socket을 반환시키는
accept()라는 메소드를 사용합니다. 여기서 반환되는 Socket은 client측
호스트정보를 가지게 될것입니다. 이로서 client와 server는 연결된 상태로 유지되고
우리는 정보를 주고 받을 수 있게됩니다.

그 정보는 bytestream을통하여 주고 받을수 있는데, 이를 입력문자스트림과
출력문자스트림으로 바꾸어 우리는 편리하게 문자스트림을 주고 받을수
있게 됩니다. 바로 우리는 이점을 이용하여 서버와 클라이언트가
서로 주는 정보를 판단하도록하였습니다. 문자 열의 첫 서두를 검사하여.
[STONE]이 나오면 서로 돌을 놓았을때 X,Y좌표를 넘겨주는 정보로 판단하고,
상대받의 돌을 그려주는 메소드에 정보를 넘겨주도록하였고
[COLOR]가 나오면 상대방이 돌의 색을 저장했을때 나의 돌색을 정하기위한
정보로 판단하게됩니다. 승패정보 또한 이렇게 정보를 주고 받을수 있도록 하였습니다.


------client-----

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

import javax.swing.JOptionPane;

class Omok_Board extends Canvas {
 public static final int BLACK = 1, WHITE = -1;
 public static final int size = 30; // 한 칸 크기
 public static final int num = 20; // 놓을 수 있는 돌 최대 갯수
 public static final int x = 30; // 시작 위치 x
 public static final int y = 30; // 시작 위치 y
 public static final int width = 30; // 돌 크기 : 가로
 public static final int height = 30; // 돌 크기 : 세로
 
 // true이면 사용자가 돌을 놓을 수 있는 상태를 의미하고,
 // false이면 사용자가 돌을 놓을 수 없는 상태를 의미한다.
 private int color; // 클라이언트 돌 색
 private int server_color; // 서버 돌 색
 private String info = "돌 선택"; // 출력 스트링
 private String str_color; // 클라이언트의 돌 색 출력 스트링
 private boolean enable = false; // 오목판 활성화 여부를 저장
 private PrintWriter writer; // 상대편에게 메시지를 전달하기 위한 스트림
 private int stone[][] = new int[num][num]; // 돌 놓은 곳 저장
  
 Omok_Board(){
  this.setVisible(true);
  this.setBackground(new Color(200, 200, 100));

  addMouseListener(new MouseAdapter() {
   public void mousePressed(MouseEvent me) { // 마우스를 누르면
    if(!enable) {// 오목판이 비활성화일 경우
     return;
    }
    else if(me.getX()>x+size*(num-1) || me.getY()>y+size*(num-1)) { // 오목판 범위를 벗어 났을 경우(아래, 오른쪽)
     return;
    }
    else if(me.getX()<(x-size/2)|| me.getY()<(y-size/2)) // 오목판 범위를 벗어 났을 경우(위, 왼쪽)
     return;
    else if(stone[(me.getX()-x+size/2)/size][(me.getY()-y+size/2)/size] != 0) // 돌이 놓여 있으면
     return;
    else { // 돌 놓음
     stone[(me.getX()-x+size/2)/size][(me.getY()-y+size/2)/size] = color;
    }
    
    // 서버에게 돌 놓은 위치 전송
    writer.println("[STONE]"+(me.getX()-x+size/2)/size + "," + (me.getY()-y+size/2)/size);
    info="상대편이 돌을 놓고 있습니다.";
    repaint();
    
    enable = false;
   }
  });
 }
 
 void reset() { // 게임 종료시 초기화
  for(int i=0;i<num;i++) {
   for(int j=0;j<num;j++) {
    stone[i][j]=0;
   }
  }
  repaint();
  setEnable(false); // 바둑판 비활성화
 }
 
 public void paint(Graphics g) {
  g.clearRect(0, 0, getWidth(), getHeight());
  
  g.setColor(Color.RED);
  g.drawString(info, 30, 20);// Info 출력 부분
  
  for(int i=0;i<num;i++) { // 라인을 그린다.
   g.setColor(Color.BLACK); // 색설정
   g.drawLine(x,y+(size*i),x+(size*(num-1)),y+(size*i)); // 가로선
   g.drawLine(x+(size*i),y, x+(size*i),y+(size*(num-1))); // 세로선
  }
  for(int i=0;i<num;i++) { // 돌을 놓는다
   for(int j=0;j<num;j++) {
    if(stone[i][j]==BLACK) { // 흑돌이 놓여있을 경우
     g.setColor(Color.BLACK);
     g.fillOval((x-size/2)+i*size, (y-size/2)+j*size, width, height);
    }
    else if(stone[i][j]==WHITE) { // 백돌이 놓여있을 경우
     g.setColor(Color.WHITE);
     g.fillOval((x-size/2)+i*size, (y-size/2)+j*size, width, height);
    }
   }
  }
 }
 
 public void stoneSelect() { // 돌 선택 메세지
  if(JOptionPane.showOptionDialog(this, "흑과 백 중 하나 선택하세요", "돌 색깔 선택",
    JOptionPane.YES_NO_OPTION,JOptionPane.QUESTION_MESSAGE,
    null, new String[]{"흑", "백"},"흑") == 0) { // 흑 선택시
   setColor(BLACK,WHITE);
   writer.println("[COLOR]" + WHITE + "," + BLACK);
  }
  else { // 백 선택시
   setColor(WHITE,BLACK);
   writer.println("[COLOR]" + BLACK + "," + WHITE);
  }
 }
 
 public void setEnable(boolean enable) { // 바둑판 활성화 변경 메소드
  this.enable = enable;
 }
 
 public void setWriter(PrintWriter writer) { // 서버와의 연결을 담당하는 PrintWriter
  this.writer = writer;
 }
 
 public void setColor(int color,int server_color) { // 돌 색 설정
  this.color = color; // 클라이언트 돌 색 설정
  this.server_color = server_color; // 서버 돌 색 설정
  
  if(color==BLACK){  // 검은 돌일 경우 선공
   setEnable(true); // 오목판 활성화
   info="돌 선택이 완료되었습니다 - 흑(선공)";
   str_color = "흑";
  }
  else { // 백 돌일 경우 후공
   setEnable(false); // 오목판 비활성화
   info="돌 선택이 완료되었습니다 - 백(후공)";
   str_color = "백";
  }
  
  repaint();
 }
 
 public void setInfo(String info) {
  this.info = info;
 }
 
 public void putOpponent(int x, int y) { // 서버의 돌을 놓는다.
  stone[x][y] = server_color;
  info="나의 턴(" + str_color + ") - 돌을 놓으세요";
  repaint();
 }
}

public class Omok_Client extends Frame {
 private Omok_Board board = new Omok_Board(); // 오목판 객체
 Socket socket = null; // 소켓
 private BufferedReader reader; // 입력 스트림
 private PrintWriter writer; // 출력 스트림
 
 public Omok_Client(String title) { // 생성자
  super(title);
  add(board);
  
  addWindowListener(new WindowAdapter() {
   public void windowClosing(WindowEvent we) {
    System.exit(0);
   }
  });
 }
 
 private void connect() { // 연결
  try {
   socket = new Socket("127.0.0.1",9002);

   reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
   writer = new PrintWriter(socket.getOutputStream(),true);
   
   board.setWriter(writer);
   board.stoneSelect();
   
   String msg;
   
   while((msg = reader.readLine()) != null) {
    if (msg.startsWith("[STONE]")) { // 서버가 돌을 놓았을 경우
     msg=msg.substring(7);
     board.setEnable(true); // 클라이언트의 턴임을 설정
     board.putOpponent(Integer.parseInt(msg.substring(0, msg.indexOf(",")))
       ,Integer.parseInt(msg.substring(msg.indexOf(",") + 1)));
    }
    else if (msg.startsWith("[COLOR]")) { // 서버가 돌 색을 지정했을 경우
     msg=msg.substring(7);
     board.setColor(Integer.parseInt(msg.substring(0, msg.indexOf(",")))
       ,Integer.parseInt(msg.substring(msg.indexOf(",") + 1)));
    }
    else if (msg.startsWith("[LOSE]")) { // 서버가 클라이언트의 패배를 알렸을 경우
     msg=msg.substring(6);
     JOptionPane.showMessageDialog(null, msg);
     board.setInfo("돌 선택");
     board.reset();
     board.stoneSelect(); // 돌 색 설정 화면 호출
    }
    else if (msg.startsWith("[WIN]")) { // 서버가 클라이언트의 승리를 알렸을 경우
     msg=msg.substring(5);
     JOptionPane.showMessageDialog(null, msg);
     board.setInfo("상대가 돌을 선택하고 있습니다.");
     board.reset();
    }
   }
  }
  catch(Exception e) {
   System.out.println(e.getMessage());
  }
  finally {
   try {
    socket.close();
   }
   catch(Exception e) { }
  }
 }
 public static void main(String[] args) {
  Omok_Client client = new Omok_Client("네트워크 오목 게임 - 클라이언트");
  client.setBounds(550,50,650,670);
  client.setVisible(true);
  client.connect();
 }
 }


--server--
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

import javax.swing.JOptionPane;

class Omok_Board extends Canvas {
 public static final int BLACK = 1, WHITE = -1;
 public static final int size = 30; // 한 칸 크기
 public static final int num = 20; // 놓을 수 있는 돌 최대 갯수
 public static final int x = 30; // 시작 위치 x
 public static final int y = 30; // 시작 위치 y
 public static final int width = 30; // 돌 크기 : 가로
 public static final int height = 30; // 돌 크기 : 세로
 
 // true이면 사용자가 돌을 놓을 수 있는 상태를 의미하고,
 // false이면 사용자가 돌을 놓을 수 없는 상태를 의미한다.
 private int color; // 서버 돌 색
 private int client_color; // 클라이언트 돌 색
 private String info = "접속 대기"; // 출력 스트링
 private String str_color; // 서버의 돌색 출력 스트링
 private boolean enable = false; // 오목판 활성화 여부를 저장
 private PrintWriter writer; // 상대편에게 메시지를 전달하기 위한 스트림
 private int stone[][] = new int[num][num]; // 돌 놓은 곳 저장
  
 Omok_Board(){
  this.setVisible(true);
  this.setBackground(new Color(200, 200, 100));
  
  addMouseListener(new MouseAdapter() {
   public void mousePressed(MouseEvent me) { // 마우스를 누르면
    if(!enable) { // 오목판이 비활성화일 경우
     return;
    }
    else if(me.getX()>x+size*(num-1) || me.getY()>y+size*(num-1)) { // 오목판 범위를 벗어 났을 경우(아래, 오른쪽)
     return;
    }
    else if(me.getX()<(x-size/2)|| me.getY()<(y-size/2)) // 오목판 범위를 벗어 났을 경우(위, 왼쪽)
     return;
    else if(stone[(me.getX()-x+size/2)/size][(me.getY()-y+size/2)/size] != 0) // 돌이 놓여 있으면
     return;
    else { // 돌 놓음
     stone[(me.getX()-x+size/2)/size][(me.getY()-y+size/2)/size] = color;
    }
    
    // 클라이언트에게 돌 놓은 위치를 전송
    writer.println("[STONE]" + (me.getX()-x+size/2)/size + "," + (me.getY()-y+size/2)/size);
    
    if(check(color)==true) { // 서버 오목 체크
     repaint();
     JOptionPane.showMessageDialog(null, "내가 이겼다"); // 승리 메세지 출력
     writer.println("[LOSE]당신이 졌습니다."); // 상대방에게 패배를 알림
     info="상대가 돌을 선택하고 있습니다."; // 메세지 수정

     reset();
     return;
    }
    info="상대편이 돌을 놓고 있습니다.";
    repaint();

    enable = false; // 턴 종료 설정
   }
  });
 }

 boolean check(int color) { // 오목 체크 메소드
  for(int i=0;i<num-4;i++) {
   for(int j=0;j<num;j++) {
    if(stone[i][j]==color)
     if(stone[i+1][j]==color)
      if(stone[i+2][j]==color)
       if(stone[i+3][j]==color)
        if(stone[i+4][j]==color)
         return true;
   }
  }
  for(int i=0;i<num;i++) {
   for(int j=0;j<num-4;j++) {
    if(stone[i][j]==color)
     if(stone[i][j+1]==color)
      if(stone[i][j+2]==color)
       if(stone[i][j+3]==color)
        if(stone[i][j+4]==color)
         return true;
   }
  }
  for(int i=0;i<num-4;i++) {
   for(int j=0;j<num-4;j++) {
    if(stone[i][j]==color)
     if(stone[i+1][j+1]==color)
      if(stone[i+2][j+2]==color)
       if(stone[i+3][j+3]==color)
        if(stone[i+4][j+4]==color)
         return true;
   }
  }
  for(int i=19;i>3;i--) {
   for(int j=0;j<num-4;j++) {
    if(stone[i][j]==color)
     if(stone[i-1][j+1]==color)
      if(stone[i-2][j+2]==color)
       if(stone[i-3][j+3]==color)
        if(stone[i-4][j+4]==color)
         return true;
   }
  }
  return false;
 }
 
 void reset() { // 게임 종료 시 초기화
  for(int i=0;i<num;i++) {
   for(int j=0;j<num;j++) {
    stone[i][j]=0;
   }
  }
  repaint();
  setEnable(false); // 바둑판 비활성화
 }
 
 public void paint(Graphics g) {
  g.clearRect(0, 0, getWidth(), getHeight());
  
  g.setColor(Color.RED);
  g.drawString(info, 30, 20); // Info 출력 부분
  
  for(int i=0;i<num;i++) { // 라인을 그린다.
   g.setColor(Color.BLACK); // 색설정
   g.drawLine(x,y+(size*i),x+(size*(num-1)),y+(size*i)); // 가로선
   g.drawLine(x+(size*i),y, x+(size*i),y+(size*(num-1))); // 세로선
  }
  for(int i=0;i<num;i++) { // 돌을 놓는다.
   for(int j=0;j<num;j++) {
    if(stone[i][j]==BLACK) { // 흑돌이 놓여있을 경우
     g.setColor(Color.BLACK);
     g.fillOval((x-size/2)+i*size, (y-size/2)+j*size, width, height);
    }
    else if(stone[i][j]==WHITE) { // 백돌이 놓여있을 경우
     g.setColor(Color.WHITE);
     g.fillOval((x-size/2)+i*size, (y-size/2)+j*size, width, height);
    }
   }
  }
 }

 
 public void stoneSelect() { // 돌 선택 메세지
  if(JOptionPane.showOptionDialog(this, "흑과 백 중 하나 선택하세요", "돌 색깔 선택",
    JOptionPane.YES_NO_OPTION,JOptionPane.QUESTION_MESSAGE,
    null, new String[]{"흑", "백"},"흑") == 0) { // 흑 선택시
   setColor(BLACK,WHITE);
   writer.println("[COLOR]" + WHITE + "," + BLACK);
  }
  else { // 백 선택시
   setColor(WHITE,BLACK);
   writer.println("[COLOR]"+ BLACK + "," + WHITE);
  }
 }
 
 public void setEnable(boolean enable) { // 바둑판 활성화 변경 메소드
  this.enable = enable;
 }
 
 public void setWriter(PrintWriter writer) { // 클라이언트와의 연결을 담당하는 PrintWriter
  this.writer = writer;
 }
 
 public void setColor(int color,int client_color) { // 돌 색 설정
  this.color = color; // 서버의 돌 색 설정
  this.client_color = client_color; // 클라이언트의 돌 색 설정
  
  if(color==BLACK){ // 검은 돌일 경우 선공
   setEnable(true);
   info="돌 선택이 완료되었습니다 - 흑(선공)";
   str_color = "흑";
  }
  else { // 흰 돌일 경우 후공
   setEnable(false);
   info="돌 선택이 완료되었습니다 - 백(후공)";
   str_color = "백";
  }
  repaint();
 }
 
 public void setInfo(String info) {
  this.info = info;
 }
 
 public void putOpponent(int x, int y) { // 클라이언트의 돌을 놓는다.
  stone[x][y] = client_color;
  info="나의 턴(" + str_color + ") - 돌을 놓으세요";
  repaint();
  
  if(check(client_color)==true) { // 클라이언트 오목 체크
   repaint();
   JOptionPane.showMessageDialog(null, "내가 졌다"); // 패배 메세지 출력
   writer.println("[WIN]당신이 이겼습니다."); // 클라이언트에게 승리를 알림
   info="돌을 선택";
   reset();
   stoneSelect(); // 돌 색 선택 화면 호출
  }
 }
}

public class Omok_Server extends Frame {
 private Omok_Board board = new Omok_Board(); // 오목판 객체
 ServerSocket serverSocket = null;
 Socket socket = null;
 private BufferedReader reader; // 입력 스트림
 private PrintWriter writer; // 출력 스트림
 
 public Omok_Server(String title) { // 생성자
  super(title);

  add(board);
  
  addWindowListener(new WindowAdapter() {
   public void windowClosing(WindowEvent we) {
    System.exit(0);
   }
  });
 }
 
 private void connect() { // 연결
  try {
   serverSocket = new ServerSocket(9002);
   
   socket = serverSocket.accept();
   reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
   writer = new PrintWriter(socket.getOutputStream(),true);
   board.setWriter(writer);
   board.setInfo("상대가 돌을 선택하고 있습니다.");
   
   String msg;
   
   while((msg = reader.readLine()) != null) {
    if (msg.startsWith("[STONE]")) { // 서버가 돌을 놓았을 경우
     msg=msg.substring(7);
     board.setEnable(true); // 서버의 턴임을 설정
     board.putOpponent(Integer.parseInt(msg.substring(0, msg.indexOf(",")))
       ,Integer.parseInt(msg.substring(msg.indexOf(",") + 1)));
    }
    else if (msg.startsWith("[COLOR]")) { // 클라이언트가 돌 색을 지정했을 경우
     msg=msg.substring(7);
     board.setColor(Integer.parseInt(msg.substring(0, msg.indexOf(",")))
       ,Integer.parseInt(msg.substring(msg.indexOf(",") + 1)));
    }
   }
  }
  catch(Exception e) {
   System.out.println(e.getMessage());
  }
  finally {
   try {
    serverSocket.close();
    socket.close();
   }
   catch(Exception e) { }
  }
 }
 public static void main(final String[] args) {
  Omok_Server server = new Omok_Server("네트워크 오목 게임 - 서버"); // 오목판 객체
  server.setBounds(0,0,650,670);
  server.setVisible(true);
  server.connect();
 }
}


 

반응형
반응형

 [[컬렉션 클래스]]

Vector클래스 : 특정형의 배열을 입력받아 동적으로 가변길이를 정의 할수 있게 해준다.

즉 크기가 확정되지 않은 배열을 사용하는 경우에 편리하다.

Vector는 확장 for문을 이용하여 객체의 끝을 체크하지않고도 하나씩 차례대로 접근할 수 있도록 한다.

for( 자료형 접근 변수명: 배열이나 컬렉션 변수명){반복코드}

이 의 소스는 아래와 같다.

public class Vector {
 public static void main(String[] args) {
  String []arr={"진달래","백합","개나리","튜율립","장미","영철","영철"};
  java.util.Vector<String> vec = new java.util.Vector<String>(4,3);//끝의 4,3중 4는 선언시 용량이고 3은 추가시 3시 가변길이가 늘어난다.
  System.out.println("vec.size() : "+vec.size());
  System.out.println("vec.capacity() : "+vec.capacity());
  for(int i=0;i<arr.length;i++)vec.add(arr[i]);
  //확장 for문 : vec의 자료형을 검사하여 아닐때까지 반복한다.
  for(String item : vec)System.out.print(item+"\n");
  System.out.println();
  System.out.println("vec.size() : "+vec.size());
  System.out.println("vec.capacity() : "+vec.capacity());
 }
}

 


  Stack 클래스 : 스택구조를 지원해주는 클래스이다. 소스는 아래와 같다.

public class Stack {
 public static void main(String[] args) {
  String []arr={"진달래","백합","개나리","튤립","장미"};
  java.util.Stack<String> stk= new java.util.Stack<String>();
  for(int i=0;i<arr.length;i++)stk.push(arr[i]);
  while(!stk.isEmpty())System.out.print(stk.pop()+"\t");
 }
}

 

  Queue와 LinkedList 클래스 : LinkedList로 구현된 Queue를 지원해주는 클래스이다. 소스는 아래와 같다.

import java.util.LinkedList;

public class QueueLink {
 public static void main(String[] args) {
  String []arr={"진달래","백합","개나리","튤립","장미"};
  LinkedList<String> que= new LinkedList<String>();
  for(int i=0;i<arr.length;i++)que.offer(arr[i]);
  while(que.peek()!=null)
   System.out.println(que.poll()+"\t");
 }
}

  Iterator 인터페이스

Iterator 인터페이스는 컬렉션 객체에 저장된 데이터에 순차적으로 하나씩 접근하고자 할때
사용된다. iterator 인터페이스는 인덱스가 아닌, 다음 메소드를 통해서 저장된 데이터를 
 하나씩 순서대로 접근하면서 가저온다.

public class Iterator {
 public static void main(String[] args) {
  String []arr={"진달래","백합","개나리","튜율립","장미","영철","영철"};
  java.util.Vector<String> vec = new java.util.Vector<String>(4,3);
  for(int i=0;i<arr.length;i++)vec.add(arr[i]);
  java.util.Iterator<String> item = vec.iterator();
  while(item.hasNext())// 순차적인 접근 가능.
   System.out.println(item.next()+"\t");  
 }
}

  Enumeration 인터페이스

 Enumeration 인터페이스는 컬렉션에 저장된  요소들을 순차적으로 열거 하면서 접근하는 
 메소드를 제공한다. 때문에 List 인터페이스로 구현한 클래스인 Vector에서 주로 사용한다. 

public class Enumeration {
 public static void main(String[] args) {
  String []arr={"진달래","백합","개나리","튜율립","장미","영철","영철"};
  java.util.Vector<String> vec = new java.util.Vector<String>(4,3);
  for(int i=0;i<arr.length;i++)vec.add(arr[i]);
  java.util.Enumeration<String> item = vec.elements();
  while(item.hasMoreElements())
   System.out.println(item.nextElement()+"\t");  
 }
}

   set 인터페이스_Hashset 클래스

set 인터페이스는 수학의 집합에서 중복을 허용하지 않듯이 중복을
 허용하지 않는 컬렉션 프레임 워크이다.

package exam07;

import java.util.HashSet;

public class SetInterface {
 public static void main(String[] args) {
  HashSet<String> set= new HashSet<String>();
  set.add("진달래");set.add("백합");
  set.add("튤립");set.add("개나리");
  set.add("백합");set.add("진달래");
  set.add("장미");
  for(String item: set)
   System.out.println(item+"\t");
 }
}

 

   set 인터페이스_Hashset 클래스

//  자바에서는 인덱스로 원하는 항목을 찾아가는 대신 값으로 즉,
//  내용 검색이 가능하도록 하는 Map인터페이스를 제공한다.
//  Map인터페이스는 키(key)와 값(value)을 하나의 쌍으로 묶어서 저장하는
//  컬렉션 클래서를 구현하는데 사용한다. 이때 키에 의해 데이터 접근이 가능하기
//  때문에 키는 중복을 허용하지 않는다 하지만 값은 중복을 허용한다.
//  Map인터페이스를 구현한 클래스로는 Hashtable,HashMap,
//  LinkedHashMap,SortedMap,TreeMap이 있다.
//  HashTable은 인덱스가 아닌 키값으로 원하는 테이블 항목을 검색하기 때문에
//  검색속도가 굉장히 빠르다.
//  자바에서는 해시 테이블을 위해서 HashTable 클래스를 제공하는데, 이 클래스로 객체로
//  생성할 경우 키와 값에 대한 데이터 타입을 지정해야 한다.

import java.util.Hashtable;
import java.util.Scanner;
import java.util.Set;
public class MapInterface {
 public static void main(String[] args) {
  Hashtable<String, Double>ht= new Hashtable<String, Double>();
  ht.put("김형중",182.5);
  ht.put("금잔디",163.6);
  ht.put("김범",180.5);
  ht.put("구준표",187.5);
  Scanner input = new Scanner(System.in);
  System.out.print("#이름을 입력하세요.");
  String key=input.nextLine();
  double height= ht.get(key);//key를 통해 데이터를 받아온다.
  System.out.println(key+"의 신장"+height);
  System.out.println("---------------------");
  Set<String>set=ht.keySet();//해시 테이블의 키에대한 Set 객체 반환받음
  for(String item:set){//
   height=ht.get(item);
   System.out.println(item+"\t"+height);
  }  
 }
}

이 컬렉션 프레임워크들은 자료형을 지원해주고 그에 관한 조작 기능 관리 기능을 지원해준다. 
이를 유용하게 이용할수 있도록 연습을 하도록하자. 


반응형

+ Recent posts