[소켓통신을 이용하여 서버와 클라이언트 메세지 주고받기]
1) 서버
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
32
33
34
35
36
37
|
package site.itwill.net;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
//클라이언트에서 보내온 메세지를 전달받아 출력하는 서버프로그램
public class EchoServerApp {
public static void main(String[] args) {
ServerSocket echoServer = null;
try {
echoServer = new ServerSocket(4000);
System.out.println("[message] Echo server Running...");
while(true) {
Socket socket = echoServer.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//클라이언트가 보내온 메세지를 읽어 화면에 출력
//=> 클라이언트가 보내온 메세지가 없는 경우 스레드 일시 중지가 된다.
System.out.println("["+socket.getInetAddress().getHostAddress()+"]" + " 님이 보내온 메세지 >> " + in.readLine());
//in.readLine(); //클라이언트가 보낸 문자를 다 읽어들인다.
socket.close();
}
} catch (IOException e) {
System.out.println("[error] 서버에 문제가 생겼습니다.");
}
}
}
|
cs |
2) 클라이언트
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
32
33
34
35
36
37
|
package site.itwill.net;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
//키보드로 메세지를 입력받아 서버에 접속하여 전달하는 클라이언트 프로그램
public class EchoClientApp {
public static void main(String[] args) throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
System.out.println("전달 메세지 입력 >> ");
String message = in.readLine();
try {
Socket socket = new Socket("192.168.14.30", 4000);
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
out.write(message);
out.flush();
socket.close();
} catch (IOException e) {
System.out.println("[에러] 서버에 접속할 수 없습니다.");
}
}
}
|
cs |
[UDP통신을 이용하여 서버와 클라이언트 메세지 주고받기]
1) send
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
32
33
34
35
36
37
38
39
40
41
42
43
44
|
package site.itwill.net;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
//키보드로 메세지를 입력받아 다른 컴퓨터에게 전달하는 UDP프로그램
public class MessageSendApp {
public static void main(String[] args) throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
System.out.println("전달 메세지 입력 >> ");
String message = in.readLine();
//DatagramSocket : 다른컴퓨터에 접속하기 위한 기능을 제공하는 클래스
//=> DatagramSocket() : 생성자를 이용하여 데이터를 보내기 위한 메소드
DatagramSocket socket = new DatagramSocket();//포트 이런거 필요없음 보내기만 하기 때문.
//String.getBytes() : string인스턴스에 저장된 문자열을 byte[]배열로 변환하여 반환하는 메소드
byte[] data = message.getBytes();
//접속하고자하는 컴퓨터의 네트워크정보를 저장한 InetAddress
InetAddress address = InetAddress.getByName("192.168.14.30");
//DatagramPacket : 다른 컴퓨터에게 값을 전달하기 위한 정보를 저장하기 위한 클래스
//=> 패킷 : 네트워크에서 값을 전달하기 위한 단위
//=>DatagramPacket(byte[] buf,int length,InetAddress address) 값을 전달하기 위한 생성자
//1) buf : 전달값, length : 패킷크기, address : 네트워크 검색
DatagramPacket packet = new DatagramPacket(data, data.length, address, 5000);
//DatagramSocket.send(DatagramPacket p) : 다른컴퓨터에게 패킷을 전달하는 메소드
socket.send(packet);
socket.close();
System.out.println("[message] 메세지를 보냈습니다.");
}
}
|
cs |
2) receive
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
32
33
|
package site.itwill.net;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
//다른컴퓨터에서 보내온 메세지를 전달받아 출력하는 UDP프로그램
public class MessageReceiveApp {
public static void main(String[] args) throws IOException {//소켓이 안만들어져서(소켓이 충돌) 생기는 오류
//데이터를 전달받기 위한 소켓생성
DatagramSocket socket = new DatagramSocket(5000);
//전달받은 데이터를 저장하기 위한 byte배열
byte[] data = new byte[256];
//DatagramPacket(data, length) :생성자로 패킷을 받기위한 메소드
DatagramPacket packet = new DatagramPacket(data, data.length);
System.out.println("[message] 메세지 수신중...");
//DatagramSocket.receive()다른 컴퓨터에서 보내온 패킷을 제공받아 저장하는 메소드
//=>패킷을 받기 전까지 스레드 일시 중지
socket.receive(packet);
//byte배열을 전달받아 String 인스턴스 생성
String message = new String(data);//문자열로 보냈으니까 문자열로 받는다.
System.out.println("[결과] 메세지 = " + message);
socket.close();
}
}
|
cs |
[소켓통신을 이용하여 채팅프로그램 만들어보기]
1) 서버
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
|
package site.itwill.net;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.sql.ClientInfoStatus;
import java.util.List;
import java.util.Vector;
//채팅서버 프로그램
//=> 클라이언트에서 보내온 메세지를 전달받아 접속될 모든 클라이언트에게 전달하는 기능
// => 클라이언트와 연결된 소켓은 새로운 스레드를 이용하여 독립적으로 동작되도록 구현
public class chatServerApp {
//현재 접속된 모든 클라이언트의 소켓정보를 저장하기 위한 Collection 필드
private List<SocketThread> clientList;
public chatServerApp() {
ServerSocket chatServer = null;
try {
chatServer = new ServerSocket(6000);
System.out.println("[message] chatting server is runinng...");
clientList = new Vector<SocketThread>();
while(true) {
try {
Socket clientSocket = chatServer.accept();//접속되는 곳
System.out.println("[connect log] "+ clientSocket.getInetAddress().getHostAddress() + " 의 컴퓨터에서 접속하였습니다.");
//소켓정보를 저장한 스레드 인스턴스를 만들어 준다.
SocketThread st = new SocketThread(clientSocket);
//콜렉션 필드에 스레드 인스턴스 추가
clientList.add(st);
//Thread 인스턴스로 새로운 스레드를 생성하여 동작
//=> run() 메소드의 명령실행
st.start();
} catch (IOException e) {
System.out.println("[error log] 클라이언트의 접속 관련 문제가 발생하였습니다.");
}
}
} catch (IOException e) {
System.out.println("[error] 서버가 정상적으로 실행되지 않습니다.");
}
}
public static void main(String[] args) {
new chatServerApp();
}
//현재 접속된 모든 클라이언트에게 메세지를 전달하는 메소드
public void sendMessage(String message) {
for(SocketThread st : clientList) {
//클라이언트와 연결된 소켓의 출력스트림으로 메세지를 ★연결되어 있는 모든 클라이언트에게★ 전달
st.out.println(message);
}
}
//클라이언트와 연결된 소켓을 이용하여 입출력 기능을 제공하기 위한 클래스
//=> 독립적인 입력과 출력 기능을 제공하기 위해 스레드를 생성하여 동작하도록 함
public class SocketThread extends Thread{
//클라이언트와 연결된 소켓정보를 저장하기 위한 필드
private Socket socket;//값을 계속 유지하기 위해 정적필드에 위치
//클라이언트가 보내온 메세지를 전달받기위한 입력스트림을 저장하기 위한 필드
private BufferedReader in;
//클라이언트에게 메세지를 전달하기 위한 출력스트림을 저장하기 위한 필드
private PrintWriter out;
//클라이언트와 연결된 소켓정보를 받아온다. -> 벡터에 담기 위해서
public SocketThread(Socket socket) {
this.socket = socket;//매개변수로 받아온 소켓을 내것으로 하겠다!
}
//새로운 스레드가 실행하기 위한 명령을 작성 \
//=> 메세지를 보내거나 받으면 됨
//==> 메세지를 전달받아 모든 클라이언트에게 전달하는 기능을 제공
@Override
public void run() {
//대화명을 저장하기 위한 변수를 선언
String aliasName = "";
try {
//소켓의 입력스트림을 제공받아 문자열을 전달할 수 있는 입력스트림으로 확장
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//소켓의 출력스트림을 제공받아 문자열을 전달 할 수 있는 출력스트림으로 확장
//=> printWriter(outputStream ot, boolean autoflush) : boolean매개변수에 true를 전달 할 경우 자동으로flush가된다.
out = new PrintWriter(socket.getOutputStream(), true);//true값을 주면 자동으로 flush가 된다.
//클라이언트에서 입력되어 전달된 대화명을 반환받아 저장
//=>스레드 일시중지(클라이언트가 대화명을 먼저 보내야함)
aliasName = in.readLine();
//현재 접속된 ★모든★ 클라이언트에게 입장 메세지를 전달
sendMessage("[" + aliasName + "] 님이 입장하셨습니다!!!");
//클라이언트에서 보내온 메세지를 현재 접속된 모든 클라이언트에게 전달하면 됨
//=> 클라이언트의 접속이 끊길때까지 반복처리하면 된다.
//=> 클라이언트가 접속을 종료할 경우 IOException이 발생
while(true) {
sendMessage("[" + aliasName + "] : " + in.readLine());
}
} catch (IOException e) {
//클라이언트가 접속을 종료한 경우 실행될 명령
//=> 클라이언트가 접속을 종료할 경우 IOException이 발생
//현재 접속된 모든 클라이언트에게 퇴장메세지를 전달
sendMessage("[" + aliasName + "] 님이 나가셨습니다!!!");
clientList.remove(this);//나를 지워라!!
System.out.println("[connect log] "+ socket.getInetAddress().getHostAddress() + " 의 컴퓨터에서 접속을 종료하였습니다.");
}
}
}
}
|
cs |
2) 클라이언트
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
|
package site.itwill.net;
import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
//채팅 클라이언트 프로그램 - Swing
// => 서버에서 보내온 메세지를 전달받아 컴퍼넌트에 출력 - 반복처리
// => 컴퍼넌트로 메세지를 입력하여 서버에 전달 - 이벤트 핸들러
public class chatClientApp extends JFrame implements ActionListener {
private static final long serialVersionUID = 1L;
private JTextField field;//입력 컴퍼넌트
private JTextArea area;//출력 컴퍼넌트
//서버와 연결될 소켓정보를 저장하기 위한 필드
private Socket socket;
//서버에서 보내온 메세지를 전달하는 입력스트림을 저장하기 위한 필드
private BufferedReader in;
//서버에 메세지를 보내는 출력스트림을 저장하기 위한 필드
private PrintWriter out;
//대화명을 저장하기 위한 필드
private String aliasName;
public chatClientApp(String title) {
super(title);
field=new JTextField();
area=new JTextArea();
JScrollPane pane=new JScrollPane(area);
getContentPane().add(field, BorderLayout.SOUTH);
getContentPane().add(pane, BorderLayout.CENTER);
field.setFont(new Font("굴림체", Font.BOLD, 20));
area.setFont(new Font("굴림체", Font.BOLD, 20));
area.setFocusable(false);
field.addActionListener(this);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setBounds(400, 50, 400, 500);
setVisible(true);
try {
//서버 접속
socket=new Socket("192.168.14.29", 6000);
//소켓의 입력스트림을 반환받아 문자열을 전달받기 위한 입력스트림으로 확장
in=new BufferedReader(new InputStreamReader(socket.getInputStream()));
//소켓의 출력스트림을 반환받아 문자열을 전달하기 위한 출력력스트림으로 확장
out=new PrintWriter(socket.getOutputStream(),true);
} catch (IOException e) {
JOptionPane.showMessageDialog(this, "서버에 접속할 수 없습니다."
, "접속오류", JOptionPane.ERROR_MESSAGE);
System.exit(0);
}
while(true) {
//입력 다이얼로그를 이용하여 대화명을 입력받아 저장
aliasName=JOptionPane.showInputDialog(this
, "대화명을 입력해 주세요.", "대화명 입력"
, JOptionPane.QUESTION_MESSAGE).trim();
if(aliasName!=null && !aliasName.equals("")) break;
JOptionPane.showMessageDialog(this, "대화명을 반드시 입력해 주세요."
, "입력오류", JOptionPane.ERROR_MESSAGE);
}
//서버에 대화명 전달
out.println(aliasName);
//서버에 보내온 메세지를 전달받아 JTextArea 컴퍼넌트에 출력 - 반복처리
while(true) {
try {
area.append(in.readLine()+"\n");
//JTextArea.setCaretPosition(int position) : JTextArea 컴퍼넌트의 포커스를 변경하는 메소드
area.setCaretPosition(area.getText().length());
} catch (IOException e) {
JOptionPane.showMessageDialog(this, "서버와의 연결이 끊어졌습니다."
, "접속오류", JOptionPane.ERROR_MESSAGE);
System.exit(0);
}
}
}
public static void main(String[] args) {
new chatClientApp("채팅 프로그램");
}
//이벤트 핸들러 메소드 - JTextField 컴퍼넌트에서 입력된 메세지를 서버로 전달하는 기능 구현
@Override
public void actionPerformed(ActionEvent e) {
//JTextField 컴퍼넌트에서 입력된 메세지를 반환받아 저장
String message=field.getText().trim();
if(!message.equals("")) {//입력 메세지가 존재할 경우
out.println(message);//서버에 메세지를 전달
field.setText("");//JTextField 컴퍼넌트 초기화
}
}
}
|
cs |
'💻 수업정리 (2020) > 자바' 카테고리의 다른 글
[5/21] 싱글톤 패턴 (0) | 2020.06.27 |
---|---|
[6/10] 네트워크 (0) | 2020.06.10 |
[6/9] 파일처리 - 텍스트를 이용하여 파일저장, 출력 응용 (0) | 2020.06.09 |
[6/8] java.io패키지 (0) | 2020.06.08 |
[6/4] 버튼입력받아 계산기 만들기 (0) | 2020.06.04 |