메인서버 구동 클래스 MainServer

서버 구동에 대해 이야기 하겠다.

우선 파일 검색은 요청자가 서버에게 검색어를 요청한다.

요청을 받으면 서버는 db에서 지금 로그인한 아이디를 추출해 ip를 뽑아낸다.

모든 아이피에게 검색어와 요청자 ip를 전송한다.

요청자한테는 검색해서 로그인되어 있는 아이디의 갯수를 보내준다.

통신은 udp로 한다.

public class MainServer extends Thread
{
 public final static int DEFAULT_PORT = 6797;
 public final static int MAX_DATA = 65507;
 byte[] buffer = new byte[MAX_DATA];
 private ResultSet rs = null;
 private String id = null;
 private InetAddress ia = null;
 private DatagramSocket ds = null;
 private DatagramPacket dp = null;
 

 public MainServer()
 {
    
 }

 public void run()
 {
  try
  {
   DatagramSocket server = new DatagramSocket(DEFAULT_PORT);   // 소켓 생성
   DatagramPacket packet = new DatagramPacket(buffer,buffer.length); // 패킷 생성
   DBconnectionClass dc = null;
   
   while(true)
   {
    try
    {
     server.receive(packet);             // 들어온 패킷을 받는다.
     int searchCount = 0;                    // 접속한 아이디 갯수를 위한 카운터
     System.out.println("패킷이 왔습니다.");              
        
     dc = new DBconnectionClass();                              ///// db 클래스 선언
     dc.connectionDB();                                                        // db연결
     rs = dc.queryDB("ipaddress","onoff = 'O'");                    // 접속한 아이디의 아이피를 레코드에 받아낸다.
     
     while(rs.next())
     {
      id = rs.getString("ipaddress");
      //if(!(id.equals(packet.getAddress().getHostAddress())))   /// 요청자 ip가 아니면
      //{
      ia = InetAddress.getByName(id);
      ds = new DatagramSocket();
      dp = new DatagramPacket(packet.getData(),packet.getLength(),ia,6798);
      ds.send(dp);
      System.out.print(id + "패킷을 보냈습니다.");
      //dp.setLength(buffer.length);
      searchCount++;
      
      
      //}
     }
     byte[] bb = String.valueOf(searchCount).getBytes();                       // 여기 부분은 요청자한테 보내줄 데이터다.
     byte[] aa = new byte[2];
     aa[0] = 1;
     aa[1] = 1;
     byte[] send = new byte[bb.length+aa.length];
     System.arraycopy(aa,0,send,0,aa.length);
     System.arraycopy(bb,0,send,aa.length,bb.length);
     ds = new DatagramSocket();
     dp = new DatagramPacket(send,send.length,packet.getAddress(),6798);
     ds.send(dp);
     System.out.println(searchCount);
     packet.setLength(buffer.length);
     dc.closeDB(); 
    
    }
    catch (SQLException se)
    {
     se.getMessage();
    }
    
   }
  }
  catch (IOException ioe)
    { 
     System.err.println(ioe);
    }
 }

요청자에서는 로그인한 유저의 갯수를 보내 그것을 상태 진행바에 추가 시켜 검색 진행상태를 확인하려 한다.

by 만두마누 | 2009/11/16 19:29 | 프로젝트2(JAVA) | 트랙백 | 덧글(0)

소스 정리 및 문제점들....(2)

이제 X 버튼 이벤트를 처리할 차례다....

class ListRemove extends MouseAdapter
{
 private DefaultListModel dlm = null;
 private JList j = null;
 public ListRemove(DefaultListModel dlm,JList j)
 {
  this.dlm = dlm;
  this.j = j;
 }
 
 public void mouseClicked(MouseEvent e)
 {
  if(e.getX() < 16 && j.getSelectedIndex() != -1)
   dlm.remove(j.getSelectedIndex());
 }
}

X버튼 이벤트이다. 간단한 클래스이다. MouseAdapter를 상속받아서 mouseClicked 메소드에서 정의 하였다.

일단 생성자에서 DefaultListModel 과 JList 를 받아온다. (메인화면의 JList와 DefaultListModel)

그리고 아이콘은 왼쪽으로 고정되어 들어가고 있다. 아이콘의 크기는 16 * 16 이다....

그러므로 마우스 클릭할때의 이벤트를 잡아 클릭했을때 좌표가 아이콘의 최대 크기인 16 보다 작으면서

또 검색어가 하나도 없을때를 대비해 getSelectedIndex 가 -1 이 아닐때만 지우도록 정의하면 간단하게 구현할수 있었다.


지금 네트워크 쪽은 공부중이라 정확히 구현이 조금 어려운거 같다. 일단 UDP 서버로 메인을 만들고

각각의 클라이언트도 전부 TCP UDP 포트를 사용해 서버를 구축해 각각의 PC 끼리 연결을 시켜주려고 한다.

메인 서버 쪽에서 하는일은 각각의 계정과 접속한 사람들의 IP 만 알고 UDP 패킷을 통해 전송만 시켜주는 역활을 하게 된다.

각각의 클라이언트에서 TCP를 이용하여 1:1 파일 보내기를 구현하려고 한다. 일단 여기서 첫번째 고민이 생긴다.

파일 공유 검색 부분인데...
 
첫번째 방법은

공유 된 파일의 정보를 전부 DB에 등록시켜 검색어를 입력할때마다 DB에서 찾아서 메인서버에서 클라이언트로 전송해주는 방법이다.

두번째 방법은

일단 접속해 있는 아이피를 메인서버가 DB에서 받아와 UDP 패킷으로 검색어를 전부 각각의 클라이언트에게로 보낸다.
 
클라이언트들은 자신의 폴더에서 검색어와 일치하는 파일이 있으면 그걸 원래 검색을 원했던 클라이언트에게로 보내준다.

첫번째 방법의 장점은 메인에서 DB에 저장시켜 찾아와 클라이언트로 전송해주니 비교적 간단히 구현이 가능할 것이라고 생각된다.

그러나 db에 수많은 공유 파일 이름들을 등록시켜야되고 접속하는 사람들이 많으면 많을수록 안좋을거라고 생각된다.

두번째 방법은 일단 db에 파일 들을 등록안해도 되니까 db서버는 상당히 가벼워 질 것이다. 문제는 구현쪽인데.... 구현이 상당히

복잡해 질거 같다. 일단 검색어를 UDP 메인 서버에 보낼때 자신의 ip도 같이 담아서 보낸다. 그리고 UDP 메인서버에서 그것을

또 각각의 클라이언트에 검색어와 ip정보를 담아 보낸다. 그래야 다시 메인서버로 오지 않고 바로 클라이언트에게 갈수 있기 때문이다.

파일 전송쪽은 아예 구현생각 자체를 해보질 않았다. 시간은 점점 주는데 아는것이 없으니 힘들다.

다음은 검색어를 입력시에 문제점이다. 왼쪽에 리스트를 통해 검색어를 확인할수 있었고 오른쪽에는 검색어를 포함한 파일들을

출력 시키기로 했다. 그런데 각 리스트들 마다 해줘야 되는데 이것을 구현하기가 조금 에메하다. 벌써 카드 레이아웃으로 지정해놨

는데....

고정적이지 않은 배열을 사용해야 될듯 한데 어떻게 해야될지 모르겠다. 리스트가 추가 될때마다 패널도 하나씩 추가해서

화면을 구성하는걸로 수정해보고 책을 찾아봐야겠다. 아직 검색도 전송도 해결못했다. 지금까지 구현해 놓은것도 다시 구현하라고

하면 못할거 같다 ㅋㅋ 이것저것 찾아보고 한거라 나름대로의 정리가 필요한거 같은데.... 블로그도 계속 짜다가 생각날때마다 한번

씩 적기때문에 자주 까먹는다. ㅋㅋ 적어도 다음주까지는 완성시켜야 추가기능과 버그 수정이 가능할텐데...

SearchData.java 이것은 UDP 패킷으로 메세지 보내는 클래스 파일이다.
 
MainServer.java 이것은 UDP 메인서버로 오는 패킷을 처리하는 클래스 파일이다.

by 만두마누 | 2009/11/10 01:04 | 프로젝트2(JAVA) | 트랙백 | 덧글(1)

소스 정리 및 문제점들....

일단 project.java 라는 코드 하나에 만들고 있었던 클래스들을 각각의 파일로 나누었다.

일단 DBconnectionClass 라고 DB 연결 쿼리 수정 닫기 까지 DB관련된 내용을 담아둔 클래스이다.

그리고 유저의 데이터를 메모리에 저장시키기 위해 UserData 라는 클래스를 만들었다.

이 클래스는 DBconnectionClass 를 상속받아서 ResultSet 객체를 통해 각각의 정보를 저장하는 클래스이다.

그다음으로는 P2pLogin 클래스이다. 이 클래스는 로그인과 회원가입에 대한 정보를 담고 있는 클래스이다.

일단 로그인 화면에서 회원가입 버튼을 누를시 또다른 생성자를 통해 회원가입 화면을 출력한다. 그래서 가입하기 버튼을 누를시

DB에 추가시키고 그 정보는 UserData 클래스를 통해 자료를 저장시키고 로그인 할수 있게 구현하였다.

다음은 Project 클래스 이다. 이것은 초기에 만들었던 클래스 인데 메인화면을 담당하고 있다. 전송화면 서버 설정화면 검색화면 을
기초로 구성하고 있고 차후에 회원 정보 수정화면과 다운폴더 보기 버튼을 만들계획이다. 아직은 문제점이 처리가 안되어서 구현까

지는 시간이 걸릴듯하다...

다음은 오늘 제작한 ListButton  클래스이다. 원래 버튼으로 구현할려고 했었다. 그런데 그게 좀 힘들어서 ... 블로그 검색을 통해 알

아냈던 방법을 여기에 적어본다. 일단 JList 에는 Object 나 Vector로 객체를 추가해 자료를 출력할수 있다. 애초에 계획은 여기에

버튼을 추가 시켜 그 버튼을 누를때 선택된 라인을 지워주는 기능을 구현하려고 했으나 자료 찾기도 힘들고 구현도 힘들어 보였다.

그래서 검색중에 이미지를 추가하는 방법이 있어서 그걸로 구현하였다.

class ListButton extends DefaultListCellRenderer
{
 public Component getListCellRendererComponent(JList lst,Object val,int idx,boolean isSelected,boolean hasFocus)
 {
  
  JLabel cp = null;  
  String txt;
  ListData ld = (ListData)val;
  txt = ld.text;
  
  
  cp = (JLabel)super.getListCellRendererComponent(lst,txt,idx,isSelected,hasFocus);
  cp.setIcon(ld.xicon);
  
  
  return cp;

 }
 
}
class ListData
 {
  String text=null;
  Icon xicon = null;
  public ListData(String s)
  {
   text = s;
   xicon = new ImageIcon("exit.gif");
  }
 }

일단 JList에 이미지를 넣기 위해서는 DefaultListCellRenderer 를 이용해야 하는 것을 알아냈다.

DefaultListCellRenderer 를 상속받는 클래스를 만들어서 getListCellRendererComponent 메소드를 오버라이딩 하여서

안에 내용을 추가 시킨다. 우선 ListData 라는 클래스를 만들어서 원하는 문자열과 아이콘 파일을 담았다.

그것을 오버라이딩한 getListCellRendererComponent 메소드에서 불러온다. 부모클래스의 getListCellRendererComponent 메소

드를 호출해서 JLabel 형식으로 받아온다 이때 문자열만 JLabel에 저장되기 때문에 JLabel.setIcon 메소드를 호출해서 아이콘을

설정해준다. 그다음 JLabel을 리턴 시켜주면 이미지가 추가된다.


대략 이렇게 된다. 원래는 X 아이콘을 오른쪽 끝에다가 두고 싶은데 구현을 못하겠다. JPanel로 만들어서 JPanel을 리턴시킬려고

했었는데 자꾸만 모양이 나빠져서 종료 아이콘을 왼쪽으로 집어 넣게 되었다.

오른쪽으로 넣고 싶은데 ..... 다음페이지에서 계속 쓰겠다.

by 만두마누 | 2009/11/10 00:46 | 프로젝트2(JAVA) | 트랙백 | 덧글(0)

로그인 화면과 회원 가입 화면 이벤트 처리

전장의 코딩을 자세히 보면 start() 메소드를 볼수 있다. 이것은 각종 이벤트를 추가 시키기 위한 메소드 이다.

내용을 살펴 보자...

private void start()
 {
  if(kf == 0){
  login_ok.addActionListener(this);
  login_cancel.addActionListener(this);
  login_gaib.addActionListener(this);
  }
  id.setFocusTraversalKeysEnabled(false);
  id.addKeyListener(getJoinAction());
  password.setFocusTraversalKeysEnabled(false);
  password.addKeyListener(getJoinAction());
  if(kf == 1){
  join_ok.addActionListener(this);
  join_cancel.addActionListener(this);
  password1.setFocusTraversalKeysEnabled(false);
  password1.addKeyListener(getJoinAction());
  password1.addFocusListener(new FocusAdapter(){public void focusLost(FocusEvent e)
   {
    if(keybool == true){
    if(password.getText().equals(((JTextField)e.getSource()).getText()) == false)
      JOptionPane.showMessageDialog(mainFrame,"비밀번호를 다시 확인해주세요.","오류",JOptionPane.ERROR_MESSAGE);
    }
   }});
  }
 }

    우선 각종 버튼 이벤트는 p2plogin 클래스 본인 자체에서 해결을 한다. 

    회원가입시 검사를 자동으로 하려고 Tab키 이벤트를 집어 넣었다. Tab키 이벤트를 집어 넣기 위해

    setFocusTraversalKeysEnabled(false) 메소드를 추가하여야한다. 기본적으로 다음 JTextField 로 포커스가 이동하게

    설정 되어 있다. 이것을 해제 하고 keyListener 를 추가 하였다. 이벤트 대상은 getJoinAction() 이라는 메소드 인데

    private KeyAdapter getJoinAction()
 {
  if(ka == null){
   ka = new KeyAdapter(){
   public void keyPressed(KeyEvent e)
   { 
    if(e.getKeyCode() == 9){
    if(e.getSource().equals(id)){
     
     String s = ((JTextField)e.getSource()).getText();
     if(s.trim().length() == 0)
      JOptionPane.showMessageDialog(mainFrame,"아이디를 적어주세요","오류",JOptionPane.ERROR_MESSAGE);
      
      else password.requestFocus();
        
     
      
        
           }

    else if(e.getSource().equals(password))
    {
     
     String s = new String(((JPasswordField)e.getSource()).getPassword());
     if(s.trim().length() == 0)
      
      JOptionPane.showMessageDialog(mainFrame,"비밀번호를 적어주세요","오류",JOptionPane.ERROR_MESSAGE);
      else{
              
       if(kf == 0)
        login_ok.requestFocus();
       else
        password1.requestFocus();
      }
       }
     
     
      
    
    else if(e.getSource().equals(password1))
    {
     
     String s = new String(password1.getPassword());
     
     if(s.trim().length() == 0){
      keybool = false;
      JOptionPane.showMessageDialog(mainFrame,"비밀번호를 적어주세요","오류",JOptionPane.ERROR_MESSAGE);
     }
     else{
      keybool = true;
      e_mail.requestFocus();
     }
     
     
     
    }
    
    } 
     }
   
   };
   
  }
  return ka;
 }

    전체적인 내용은 keyAdapter를 이용해 tab키를 눌렀을시 입력한 내용이 없으면 오류 창을 띄우는 내용이다.

    이거 짜는데 고생좀했다. 생각보다 구현이 힘들었다. 비밀번호 확인 같은 경우 Focus 이벤트를 추가해서 

    Focus 가 이동했을시 비밀번호와 비교시켜 다르면 오류창을 뜨게 만들었다. 
    
    지금 현재 로그인 완성까지 구현해 놓았다. 블로그에 적기가 소스가 너무 더러워서 민망해서 못올리겠다.

    하면서 조금씩 정리하면서 올리고 있는중인데 그래도 더럽다... 정신 없고 

    다시 메인프레임으로 넘어가니까 변수명을 대충 만들어서 그런지 못 알아보겠다... 

    다시 천천히 수정중이다..

    어떻게 하면 한눈에 알아볼수 있게 짤수 있을까????? 정말 어려운거 같다.

    네트워크쪽은 솔직히 걱정이다. 정말 짜기 힘들거 같다.

    다음은 db에 관해 올리겠다.
    

by 만두마누 | 2009/11/02 04:06 | 프로젝트2(JAVA) | 트랙백 | 덧글(1)

로그인 화면과 회원가입 화면 제작

일단 제작 화면을 올린다...





    일단 우섭이의 소스를 가져와서 JDialog로 변경했다. 메인프레임과 연결 시키기 위해 JDialog를 사용했다.

    로그인창에서 쓰던 기존 id 와 password JPasswordField 를 회원가입창으로 그대로 가져왔다.

    우선 클래스를 생성해 jdialog 를 상속받는다.. ActionListener도 추가 시켜주고...

    메인 프레임에서 jdialog 를 호출시켰다.

    우선 생성자로 2개를 생성했다. 하나의 생성자는 로그인 화면을 다른 하나의 생성자는 회원가입 화면을 만들었다.
    
    class P2pLogin extends JDialog implements ActionListener
{
 private JPanel loginPane = null;
 private JTextField id = null;
 private JTextField name = null;
 private JPasswordField password = null;
 private JPasswordField password1 = null;
 private JTextField e_mail = null;
 private JTextField phone = null;
 private JTextField phone1 = null;
 private JTextField phone2 = null;
 private JTextField address1 = null;
 private JTextField address2 = null;
 private JFrame mainFrame = null;
 private boolean bexit = true;
 private Connection conn = null;
 private Statement stmt = null;
 private JButton login_ok = null;
 private JButton login_cancel = null;
 private JButton login_gaib = null;
 private JButton join_ok = null;
 private JButton join_cancel = null;
 private String[] id_check = {"아이디를 적어주세요","사용가능합니다.","중복입니다. 다시해주세요"};
 private KeyAdapter ka = null;
 private boolean keybool = false;
 private int kf = 0;
 private ResultSet rs = null;
 private UserData ud = null;
 private JLabel idshow;
 
 //////////////////////////////////////////////////////////////
 
 // 로그인 창 만들기

 //////////////////////////////////////////////////////////////

 public P2pLogin(JFrame j,JLabel show,UserData ud)
 {
  
  super(j,"P2P Login",true);
  mainFrame = j;
  idshow = show;
  this.setLayout(new BorderLayout());
  kf = 0;
  this.ud = ud;
  
  JLabel loginLabel = new JLabel("   ID와 비밀번호를 입력해주세요",JLabel.CENTER);
  this.add(loginLabel,BorderLayout.NORTH);
  this.add(getloginPane(),BorderLayout.CENTER);
  JPanel loginButton = new JPanel();
  login_ok = new JButton("로그인");
  login_cancel = new JButton("취소");
  login_gaib = new JButton("회원가입");
  loginButton.add(login_ok);
  loginButton.add(login_cancel);
  loginButton.add(login_gaib);
  this.add(loginButton,BorderLayout.SOUTH);
  this.pack();
  int x = (int)Toolkit.getDefaultToolkit().getScreenSize().getWidth()/2 - this.getWidth()/2;
  int y = (int)Toolkit.getDefaultToolkit().getScreenSize().getHeight()/2 - this.getHeight()/2;
  this.setLocation(x,y);
  this.start();
  this.setVisible(true);
  this.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE,bexit);


  
 }

 //////////////////////////////////////////////////////////////

 // 회원 가입창 생성

 //////////////////////////////////////////////////////////////

 public P2pLogin(JFrame j,String s)
 {
  super(j,s,true);
  mainFrame = j;
  kf = 1;
  this.setLayout(new BorderLayout());
  this.add(new JLabel("정확한 정보를 입력해주세요"),BorderLayout.NORTH);
  JPanel joinPane = new JPanel();
  joinPane.setLayout(null);
  JPanel login = getloginPane();
  login.setBounds(0,0,400,60);
  password1 = new JPasswordField(10);
  JPanel jj = new JPanel(new GridLayout(6,2));
  jj.add(new JLabel("비밀번호확인",JLabel.CENTER));
  JPanel ps = new JPanel(new FlowLayout(FlowLayout.LEFT));
  ps.add(password1);
  jj.add(ps);
  name = new JTextField(10);
  jj.add(new JLabel("이름",JLabel.CENTER));
  JPanel jn = new JPanel(new FlowLayout(FlowLayout.LEFT));
  jn.add(name);
  jj.add(jn);
  jj.add(new JLabel("E-Mail",JLabel.CENTER));
  JPanel ps1 = new JPanel(new FlowLayout(FlowLayout.LEFT));
  e_mail = new JTextField(15);
  ps1.add(e_mail);
  jj.add(ps1);
  jj.add(new JLabel("핸 드 폰",JLabel.CENTER));
  JPanel ps2 = new JPanel(new FlowLayout(FlowLayout.LEFT));
  JPanel ps3 = new JPanel(new FlowLayout(FlowLayout.LEFT));
  ps3.setPreferredSize(new Dimension(40,30));
  JPanel ps4 = new JPanel(new FlowLayout(FlowLayout.LEFT));
  
  phone = new JTextField(3);
  phone1 = new JTextField(4);
  phone2 = new JTextField(4);
  ps2.add(phone);
  ps2.add(new JLabel("-"));
  ps2.add(phone1);
  ps2.add(new JLabel("-"));
  ps2.add(phone2);
  jj.add(ps2);
  address1 = new JTextField(17);
  ps3.add(address1);
  address2 = new JTextField(17);
  ps4.add(address2);
  
  jj.add(new JPanel(new FlowLayout(FlowLayout.CENTER)).add(new JLabel("주 소",JLabel.CENTER)));
  jj.add(ps3);
  jj.add(new JPanel(new FlowLayout(FlowLayout.CENTER)).add(new JLabel("",JLabel.CENTER)));
  jj.add(ps4);
  
  jj.setBounds(0,60,400,200);
  joinPane.add(login);
  joinPane.add(jj);
  join_ok = new JButton("가입하기");
  join_cancel = new JButton("가입취소");

  JPanel okButton = new JPanel(new FlowLayout(FlowLayout.CENTER));
  okButton.setBounds(30,260,400,50);
  okButton.add(join_ok);
  okButton.add(join_cancel);
  joinPane.add(okButton);
  this.add(joinPane,BorderLayout.CENTER);
  this.setSize(500,400);
  this.setLocation((int)(Toolkit.getDefaultToolkit().getScreenSize().getWidth()/2 - this.getWidth()/2),(int)(Toolkit.getDefaultToolkit().getScreenSize().getHeight()/2 - this.getHeight()/2));
  this.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
  this.start();
  this.setVisible(true);


 }

//////////////////////////////////////////////////////////////

 // 로그인 패널 만들기

 //////////////////////////////////////////////////////////////

 private JPanel getloginPane()
 {
  if(loginPane == null){
  id = new JTextField(10);
  password = new JPasswordField(10);
  loginPane = new JPanel(new GridLayout(2,2));
  loginPane.add(new JLabel("아    이    디",JLabel.CENTER));
  JPanel idPane = new JPanel(new FlowLayout(FlowLayout.LEFT));
  idPane.add(id,JTextField.CENTER);
  loginPane.add(idPane);
  loginPane.add(new JLabel("비 밀 번 호",JLabel.CENTER));
  JPanel passwordPane = new JPanel(new FlowLayout(FlowLayout.LEFT));
  passwordPane.add(password);
  loginPane.add(passwordPane);
  }
  return loginPane;
 }



    기초 소스 이다. 여기는 많은 변수를 사용한다 회원가입도 해야되기 때문에....

    각종 정보를 저장 하는 변수와 db를 연결하기 와한 conn변수 , stmt 변수등도 있고 ... 

    kf 변수는 0과 1을 저장한다. 로그인창을 생성할때는 0을 나타내고 회원가입창을 나타낼때는 1을 나타낸다.

    각종 이벤트를 위해 나누었다. 

    UserData 클래스는 db에서 로그인할시 가져오는 자료를 저장하기 위해 사용한 클래스 이다.

    기초 외관은 이렇게 만들었다.
    

by 만두마누 | 2009/11/02 03:58 | 프로젝트2(JAVA) | 트랙백 | 덧글(1)

<< 이전 페이지다음 페이지 >>