반응형
Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
Tags
- 자바스크립트 코딩테스트
- typescript
- 리액트
- 평일코딩
- 정보처리기사요약
- 자바스크립트
- 리액트네이티브
- 오라클
- php
- spring
- 국비IT
- 정보처리기사정리
- 정보처리기사실기
- 코딩테스트
- 정보처리기사실기요약
- 이안의평일코딩
- Java의정석
- javascript
- 타입스크립트
- VUE
- 국비코딩
- 정보처리기사실기정리
- react
- Oracle
- 자바의정석
- ReactNative
- 자스코테
- 정보처리기사
- CSS
- 스프링
Archives
- Today
- Total
이안의 평일코딩
JAVA의 정석 35일차 - 자바 마지막 예제 본문
반응형
2020.07.31(금)
1. Client, Server => 공통으로 사용되는 클래스
프로그램의 기능 설정 => 내부 프로토콜 (서버와 클라이언트의 약속)
Client - Server 접속
Socket s = new Socket("",PORT) => 서버주소
==
서버 정보
클라이언트 정보를 확인
클라이언트 IP, PORT ===합쳐서==> Socket
=> Socket s = ss.accept();
==
클라이언트 정보
Client 접속 Server => 저장장소 (Vector)에 클라이언트 IP, PORT
통신 클라이언트 => 요청, 서버 => 요청처리
웹 서버 =>
Function
package com.sist.common;
public class Function {
// 로그인 처리 => 이미 로그인 된 사람
public static final int LOGIN=100;
public static final int MYLOG=110;
// 방만들기
// 방들어가기
// 방나가기
// 대기실 수정
// 대기실 채팅
public static final int WAITCHAT=500;
// 방채팅
// 쪽지보내기
// 채팅 종료
// 1:1 게임
}
Server
package com.sist.server;
// network => net => 라이브러리(import로 가져옴)
import java.util.*;
import com.sist.common.Function;
import java.io.*; // 입출력 (서버와 클라이언트의 데이터 주고 받기)
import java.net.*; // 다른 컴퓨터와 연결
/*
* 일반 서버 (Application) => Socket(연결 기계 => 소프트웨어로 제작)
* 웹서버 => URL
* ========================================연결지향적 프로그램 TCP
* TCP
*/
// Server => 접속만 담당 => 저장
// Client => 실제 통신 담당 => 클라이언트마다 따로 통신= > 쓰레드 이용
public class Server implements Runnable{
private ServerSocket ss; // 접속을 받는 클래스 => 정보 저장
private final int PORT = 9875;
// 클라이언트 접속시에 정보 저장(IP, PORT)
private Vector<Client> waitVc = new Vector<Client>();
// 쓰레드에서 동기화 프로그램
// 서버 가동
public Server() {
try {
ss = new ServerSocket(PORT);
/*
* bind() => IP, PORT 묶어주는 역할
* ===> 핸드폰 (개통)
* listen() => 대기상태 (클라이언트가 접속하기 전까지 대기)
*/
System.out.println("Server Start...");
}catch(Exception ex) {}
}
// 클라이언트가 접속을 했을 경우 => 각자 통신이 가능하게 쓰레드와 연결
@Override
public void run() {
try {
while(true) {
Socket s = ss.accept();
// accept() : 특수한 메소드 => 클라이언트가 접속시에만 호출되는 메소드
Client client = new Client(s);
client.start(); // 클라이언트와 통신 승인
}
}catch(Exception ex) {}
}
public static void main(String[] args) {
// 서버 가동
Server server = new Server();
new Thread(server).start();
// Server클래스에 있는 run()을 호출
}
// 내부 클래스 => Server가 가지고 있는 데이터 쉽게 공유가 가능하게 만든다
class Client extends Thread{
Socket s; // 클라이언트와 연결
BufferedReader in; // 클라이언트로부터 요청을 받는다
OutputStream out; // 요청을 처리한 다음에 결과를 응답
String id,name,sex,pos; // 변수 설정
public Client(Socket s) {
try {
this.s = s;
in = new BufferedReader(new InputStreamReader(s.getInputStream()));
// 클라이언트 요청한 메소드를 읽어오는 메모리 공간
out = s.getOutputStream();
}catch(Exception ex) {}
}
// 통신 ? => 기능(요청 처리)
public void run() {
try {
while(true) {
// 클라이언트가 요청한 내용을 받는다
String msg = in.readLine();
StringTokenizer st = new StringTokenizer(msg,"|");
int protocol = Integer.parseInt(st.nextToken());
// 100|id|대화명|성별
switch(protocol) {
case Function.LOGIN:{
// 로그인 처리
// 데이터값 받기
id = st.nextToken();
name = st.nextToken();
sex = st.nextToken();
pos = "대기실"; // 사용자의 기본 정보
// 접속한 모든 사용자 => 로그인한 정보를 보내준다
this.messageAll(Function.LOGIN+"|"+id+"|"+name+"|"+sex+"|"+pos);
// 접속한 사람의 정보를 저장
waitVc.add(this);
// Client client = new Client();
messageTo(Function.MYLOG+"|"+id);
// 로그인창에서 => 대기실창으로 변경
for(Client user:waitVc) {
messageTo(Function.LOGIN+"|"+user.id+"|"+user.name+"|"+user.sex+"|"+user.pos);
}
// 입장메세지 출력
messageAll(Function.WAITCHAT+"|{☞"+name+"님이 입장하셨습니다]");
// 개설된 방정보 전송
}
break;
case Function.WAITCHAT:{
messageAll(Function.WAITCHAT+"|["+name+"]"+st.nextToken());
}
break;
}
}
}catch(Exception ex) {}
}
// 응답 처리
// 개인적으로 전송
public synchronized void messageTo(String msg) {
// synchronized
/*
* 쓰레드는 default : 비동기화
* synchronized => 동기화
*/
try {
out.write((msg+"\n").getBytes());
//인코딩 ==> 디코딩
}catch(Exception ex) {}
}
// 전체적으로 응답
public synchronized void messageAll(String msg) {
try {
for(Client user:waitVc) {
user.messageTo(msg);
}
}catch(Exception ex) {}
}
}
}
WaitRoom
package com.sist.client;
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;
public class WaitRoom extends JPanel{
JTable table1, table2;
DefaultTableModel model1, model2;
JTextField tf;
JTextArea ta;
JButton b1, b2, b3, b4, b5, b6;
JScrollBar bar;
public WaitRoom() {
String[] col1 = {"방이름", "공개/비공개", "인원"};
String[][] row1 = new String[0][3];
model1 = new DefaultTableModel(row1, col1);
table1 = new JTable(model1);
JScrollPane js1 = new JScrollPane(table1);
String[] col2 = {"ID", "대화명", "성별", "위치"};
String[][] row2 = new String[0][3];
model2 = new DefaultTableModel(row2, col2);
table2 = new JTable(model2);
JScrollPane js2 = new JScrollPane(table2);
ta = new JTextArea();
ta.setEditable(false);
JScrollPane js3 = new JScrollPane(ta);
bar = js3.getVerticalScrollBar();
tf = new JTextField();
b1 = new JButton("방만들기");
b2 = new JButton("방들어가기");
b3 = new JButton("정보보기");
b4 = new JButton("쪽지보내기");
b5 = new JButton("일대일게임");
b6 = new JButton("나가기");
// 배치
setLayout(null);
js1.setBounds(10, 15, 600, 500);
js2.setBounds(10, 520, 600, 350);
add(js1);
add(js2);
js3.setBounds(615, 15, 390, 465);
add(js3);
tf.setBounds(615, 485, 390, 30);
add(tf);
JPanel p = new JPanel();
p.setLayout(new GridLayout(3,2,5,5));
p.add(b1); p.add(b2);
p.add(b3); p.add(b4);
p.add(b5); p.add(b6);
p.setBounds(615, 520, 390, 350);
add(p);
}
}
login
package com.sist.client;
import javax.swing.*;
import java.awt.*;
/*
* class JPanel extends Object
* class Login extends JPanel
*/
public class Login extends JPanel{
// 스킨
private Image back;
private JLabel la1,la2,la3;
// Login
JTextField tf;
JTextField pf;
JButton b1,b2;
JRadioButton rb1, rb2;
// MainForm
public Login()
{
// 이미지 정보 읽기
back=Toolkit.getDefaultToolkit().getImage("c:\\javaDev\\back.jpg");
setLayout(null);// 직접배치
la1=new JLabel("아이디",JLabel.RIGHT);
la1.setBounds(745, 720, 80, 30);
tf=new JTextField();
tf.setBounds(830, 730, 150, 30);
add(la1);add(tf);
la2=new JLabel("대화명",JLabel.RIGHT);
la2.setBounds(745, 765, 80, 30);
pf=new JTextField();
pf.setBounds(830, 765, 150, 30);
// 980-745= 235
add(la2);add(pf);
rb1 = new JRadioButton("남자");
rb2 = new JRadioButton("여자");
ButtonGroup bg = new ButtonGroup();
bg.add(rb1); bg.add(rb2);
rb1.setSelected(true);
la3 = new JLabel("성별",JLabel.RIGHT);
la3.setBounds(745, 800, 80, 30);
rb1.setBounds(830, 800, 70, 30);
rb2.setBounds(910, 800, 70, 30);
add(la3);add(rb1);add(rb2);
b1=new JButton("로그인");
b2=new JButton("취소");
JPanel p=new JPanel();
p.add(b1);
p.add(b2);
p.setOpaque(false);
p.setBounds(745, 850, 235, 35);
add(p);
}
@Override
protected void paintComponent(Graphics g) {
g.drawImage(back,0,0,getWidth(),getHeight(),this);
}
}
ClientMainFrame
package com.sist.client;
import java.util.*;
import javax.swing.*;
import com.sist.common.Function;
import java.awt.*;
import java.awt.event.*;
////////////////// 네트워크 관련
import java.net.*;
import java.io.*;
public class ClientMainFrame extends JFrame implements ActionListener, Runnable{
CardLayout card = new CardLayout();
Login login = new Login();
WaitRoom wr = new WaitRoom();
// 네트워크
Socket s; // 전화기
BufferedReader in; // 수신
OutputStream out; // 송신
public ClientMainFrame() {
setLayout(card);
add("LOGIN",login);
add("WR",wr);
setSize(1200,950);
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
login.b1.addActionListener(this);
login.b2.addActionListener(this);
wr.tf.addActionListener(this);
}
public static void main(String[] args) {
new ClientMainFrame();
}
public void connection(String id, String name, String sex) {
// 서버연결 => 로그인 요청
try {
s = new Socket("localhost",9875); //서버주소, PORT
in = new BufferedReader(new InputStreamReader(s.getInputStream()));
out = s.getOutputStream();
// 연결이 되면 로그인요청
out.write((Function.LOGIN+"|"+id+"|"+name+"|"+sex+"\n").getBytes());
}catch(Exception ex) {}
// 연결이 되면 => 서버부터 지시를 받는다
new Thread(this).start();
}
@Override
public void actionPerformed(ActionEvent e) {
if(e.getSource()==login.b1) {
String id = login.tf.getText();
String name = login.pf.getText();
String sex = "";
if(login.rb1.isSelected())
sex="남자";
else
sex="여자";
connection(id, name, sex);
}
else if(e.getSource()==wr.tf) {
// 입력된 데이터 읽기
String msg = wr.tf.getText();
if(msg.length()<1) return;
try {
out.write((Function.WAITCHAT+"|"+msg+"\n").getBytes());
}catch(Exception ex) {}
wr.tf.setText("");
}
}
@Override
public void run() {
try {
while(true) {
String msg = in.readLine();
StringTokenizer st = new StringTokenizer(msg, "|");
int protocol = Integer.parseInt(st.nextToken());
switch(protocol) {
case Function.LOGIN:{
String[] data = {
st.nextToken(),
st.nextToken(),
st.nextToken(),
st.nextToken(),
};
wr.model2.addRow(data);
}
break;
case Function.MYLOG:{
setTitle(st.nextToken());
card.show(getContentPane(), "WR");
}
break;
case Function.WAITCHAT:
{
wr.bar.setValue(wr.bar.getMaximum());
wr.ta.append(st.nextToken()+"\n");
}
break;
}
}
}catch(Exception ex) {}
}
}
반응형
'Back-end > Java' 카테고리의 다른 글
JAVA - 채팅 프로그램 (0) | 2020.08.04 |
---|---|
JAVA의 정석 34일차 - 네트워크 (0) | 2020.07.30 |
JAVA의 정석 33일차 - 영화 정보 프로그램(2) (0) | 2020.07.29 |
JAVA의 정석 32일차 - 영화 정보 프로그램(1) (0) | 2020.07.28 |
JAVA의 정석 31일차 - 입출력 I/O (0) | 2020.07.27 |
Comments