MultiChatClient
Socket 객체 생성& 송수신 스레드 생성 및 실행
public void start() {
//서버와 통신할 수 있는 Socket 만들고 서버 접속
Socket 변수명 = null;
try {
socket = new Socket("IP주소", 포트번호);
System.out.println("멀티챗 서버에 접속했습니다.");
//송신용 스레드 생성 및 실행
ClientSender 변수명 = new ClientSender(Socket_변수명);
ClientSender_변수명.start();
//수신용 스레드 생성 및 실행
ClientReceiver 변수명 = new ClientReceiver(Socket_변수명);
ClientReceiver_변수명.start();
} catch (IOException e) {
e.printStackTrace();
}
}
- 예시
더보기
public void start() {
//서버와 통신할 수 있는 Socket 만들고 서버 접속
Socket socket = null;
try {
socket = new Socket("192.168.144.~", 7777);
System.out.println("멀티챗 서버에 접속했습니다.");
//송신용 스레드 생성 및 실행
ClientSender sender = new ClientSender(socket);
sender.start();
//수신용 스레드 생성 및 실행
ClientReceiver receiver = new ClientReceiver(socket);
receiver.start();
} catch (IOException e) {
e.printStackTrace();
}
}
ClientSender extends Thread
- 메시지 전송을 위한 스레드 클래스
- getOutputStream() 메소드 : 전송할 데이터 출력
- writeUTF(String str) : UTF-8 형식으로 코딩된 문자열 출력
private DataOutputStream 변수명;
private Scanner scan;
public ClientSender(Socket socket) {
scan = new Scanner(System.in);
try {
DataOutputStream_변수명 = new DataOutputStream(socket.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
try {
if(DataOutputStream_변수명 != null) { //대화명
//시작하자마자 자신을 대화명을 서버로 전송하기
System.out.println("대화명 >>");
DataOutputStream_변수명.writeUTF(scan.nextLine());
}
while (DataOutputStream_변수명 != null) {
//이제부터는 일반 채팅메시지 전송하기
DataOutputStream_변수명.writeUTF(scan.nextLine());
}
}catch (IOException e) {
e.printStackTrace();
}
}
- 예시
더보기
class ClientSender extends Thread{
private DataOutputStream dos;
private Scanner scan;
public ClientSender(Socket socket) {
scan = new Scanner(System.in);
try {
dos = new DataOutputStream(socket.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
try {
if(dos != null) { //대화명
//시작하자마자 자신을 대화명을 서버로 전송하기
System.out.println("대화명 >>");
dos.writeUTF(scan.nextLine());
}
while (dos != null) {
//이제부터는 일반 채팅메시지 전송하기
dos.writeUTF(scan.nextLine());
}
}catch (IOException e) {
e.printStackTrace();
}
}
}
ClientReceiver extends Thread
- 메시지 수신을 위한 스레드 클래스
- getInputStream() : 전송하는 데이터를 읽음
- String readUTF() : UTF-8 형식으로 코딩된 문자열 읽음
class ClientReceiver extends Thread{
private DataInputStream 변수명;
public ClientReceiver(Socket socket) {
try {
DataInputStream_변수명 = new DataInputStream(socket.getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
try {
while (DataInputStream_변수명 != null) {
//서버로부터 받은 메시지 콘솔에 출력하기
System.out.println(DataInputStream_변수명.readUTF());
}
}catch (IOException e) {
e.printStackTrace();
}
}
}
- 예시
더보기
class ClientReceiver extends Thread{
private DataInputStream dis;
public ClientReceiver(Socket socket) {
try {
dis = new DataInputStream(socket.getInputStream());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void run() {
try {
while (dis != null) {
//서버로부터 받은 메시지 콘솔에 출력하기
System.out.println(dis.readUTF());
}
}catch (IOException e) {
e.printStackTrace();
}
}
}
Main
public static void main(String[] args) {
new MultiChatClient().start();
}
}
MultiChatServer
serverStart
- 대화명을 키, 해당 소켓을 값으로 하는 Map객체 변수 선언 & 생산자 선언(컬렉션 동기화)
- 다른 client가 동시에 접속할 수 있으므로 동기화 진행
스레드 동기화란?
하나의 객체을 여러개의 스레드가 공유해서 사용할 때 하나의 스레드가 객체를 사용중이면 다른 스레드를 사용할 수 없으며 lock 걸어두는 것
private Map<String, Socket> 변수명;
public MultiChatServer() {
Map<String, Socket>_변수명 = Collections.synchronizedMap(new HashMap<String, Socket>());
}
ServerSocket_변수명 = null;
Socket Socket_변수명 = null;
try {
ServerSocket_변수명 = new ServerSocket(포토번호);
while(true) { //무한 루프
// 클라이언트의 접속을 대기
Socket_변수명 = ServerSocket_변수명.accept();
System.out.println("[" + Socket_변수명.getInetAddress() + " : "
+ Socket_변수명.getPort() + "] 에서 접속하였습니다.");
// 사용자가 보내준 메시지를 받아서 처리하는 스레드 생성 및 실행
ServerRecevier 변수명 = new ServerRecevier(Socket_변수명);
ServerRecevier_변수명.start();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
- 예시
더보기
private Map<String, Socket> clients;
public MultiChatServer() {
clients = Collections.synchronizedMap(new HashMap<String, Socket>());
}
public void serverStart() {
ServerSocket server = null;
Socket socket = null;
try {
server = new ServerSocket(7777);
System.out.println("서버가 시작되었습니다.");
while(true) {
// 클라이언트의 접속을 대기
socket = server.accept();
System.out.println("[" + socket.getInetAddress() + " : "
+ socket.getPort() + "] 에서 접속하였습니다.");
// 사용자가 보내준 메시지를 받아서 처리하는 스레드 생성 및 실행
ServerRecevier sr = new ServerRecevier(socket);
sr.start();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
sendMessage(String msg)
- Map에 저장된 모든 접속한 사람들에게 안내메서지 전송하기 위한 메서드
- param (msg) : 전송할 메서지
- Iterator 이용해서 Map에 있는 키값 전체 출력
- DataOutputStream : 해당 사용자에게 메시지 보내기
- getOutputStream 객체 만들어서 꺼냄
public void sendMessage(String msg){
Iterator<String> 변수명 = Map<String, Socket>_변수명.keySet().iterator();
while (Iterator_변수명.hasNext()) {
try {
String 변수명 = Iterator_변수명.next(); // 대화명
// 해당 사용자에게 메시지 보내기
//getgetOutputStream 객체 만들어서 꺼냄
new DataOutputStream(
clients.get(변수명).getOutputStream()).writeUTF(msg);
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
더보기
public void sendMessage(String msg){
Iterator<String> it = clients.keySet().iterator();
while (it.hasNext()) {
try {
String name = it.next(); // 대화명
// 해당 사용자에게 메시지 보내기
//getgetOutputStream 객체 만들어서 꺼냄
new DataOutputStream(
clients.get(name).getOutputStream()).writeUTF(msg);
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
sendMessage(String msg, String from)
- 파라미터 2개 메소드가 있어서 오버로딩으로 하나 더 생성
- param (msg) : 전송할 메서지
- param (from) : 메시지 보낸 대화명
public void sendMessage(String msg, String from){
sendMessage("[" +from + "]"+ msg);
}
ServerRecevier extends Thread
- 서버에서 클라이언트로부터 수신한 메세지를 처리하기 위한 클래스
class ServerRecevier extends Thread{
private Socket 변수명;
private DataInputStream 변수명;
private String 변수명;
public ServerRecevier(Socket socket) {
this.Socket_변수명 = socket;
try {
DataInputStream_변수명 = new DataInputStream(socket.getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
try {
// 서버에서는 클라이언트가 보내온 최초의 메시지, 즉 대화명을 수신해야 한다.
String_변수명 = DataInputStream_변수명.readUTF();
// 대화명을 받아서 다른 모든 클라이언트들에게 대화방 참여 메시지를 보낸다.
sendMessage("#" + String_변수명 + "님이 입장했습니다.");
// 대화명을 사용하여 소켓객체를 Map에 저장한다.
clients.put(String_변수명, Socket_변수명);
System.out.println("현재 서버 접속자 수는 " + clients.size() + "명 입니다.");
// 이 이후의 처리는 반복문으로 처리한다.
// 클라이언트가 보내온 메시지(대화내용)를 접속한 다른 모든 클라이언트
while (DataInputStream_변수명 != null) {
//name 앞에 누구인지 출력하기 위한용
sendMessage(DataInputStream_변수명.readUTF(),String_변수명);
}
} catch (IOException ex) {
ex.printStackTrace();
}finally {
//이 부분이 실행된다는것은 클라이언트와 접속에 문제가 생겼다는 의미
// 그래서 접속종료 처리를 한다.
sendMessage(String_변수명 + "님이 나가셧습니다.");
// Map에서 해당 사용자를 삭제한다.
clients.remove(String_변수명);
System.out.println("[" + Socket_변수명.getInetAddress() + " : "
+ Socket_변수명.getPort() + "] 에서 종료하였습니다.");
System.out.println("현재 서버 접속자 수는 " + clients.size() + "명 입니다.");
}
}
}
- 예시
더보기
class ServerRecevier extends Thread{
private Socket socket;
private DataInputStream dis;
private String name;
public ServerRecevier(Socket socket) {
this.socket = socket;
try {
dis = new DataInputStream(socket.getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
try {
// 서버에서는 클라이언트가 보내온 최초의 메시지, 즉 대화명을 수신해야 한다.
name = dis.readUTF();
// 대화명을 받아서 다른 모든 클라이언트들에게 대화방 참여 메시지를 보낸다.
sendMessage("#" + name + "님이 입장했습니다.");
// 대화명을 사용하여 소켓객체를 Map에 저장한다.
clients.put(name, socket);
System.out.println("현재 서버 접속자 수는 " + clients.size() + "명 입니다.");
// 이 이후의 처리는 반복문으로 처리한다.
// 클라이언트가 보내온 메시지(대화내용)를 접속한 다른 모든 클라이언트
while (dis != null) {
//name 앞에 누구인지 출력하기 위한용
sendMessage(dis.readUTF(),name);
}
} catch (IOException ex) {
ex.printStackTrace();
}finally {
//이 부분이 실행된다는것은 클라이언트와 접속에 문제가 생겼다는 의미
// 그래서 접속종료 처리를 한다.
sendMessage(name + "님이 나가셧습니다.");
// Map에서 해당 사용자를 삭제한다.
clients.remove(name);
System.out.println("[" + socket.getInetAddress() + " : "
+ socket.getPort() + "] 에서 종료하였습니다.");
System.out.println("현재 서버 접속자 수는 " + clients.size() + "명 입니다.");
}
}
}
main
public static void main(String[] args) {
new MultiChatServer().serverStart();
}
원본
MultiChatServer
더보기
package kr.or.ddit.tcp;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class MultiChatServer {
// 대화명을 키, 해당 소켓을 값으로 하는 Map객체 변수 선언
private Map<String, Socket> clients;
public MultiChatServer() {
clients = Collections.synchronizedMap(new HashMap<String, Socket>());
}
public void serverStart() {
ServerSocket server = null;
Socket socket = null;
try {
server = new ServerSocket(7777);
System.out.println("서버가 시작되었습니다.");
while(true) {
// 클라이언트의 접속을 대기
socket = server.accept();
System.out.println("[" + socket.getInetAddress() + " : "
+ socket.getPort() + "] 에서 접속하였습니다.");
// 사용자가 보내준 메시지를 받아서 처리하는 스레드 생성 및 실행
ServerRecevier sr = new ServerRecevier(socket);
sr.start();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
/**
* 대화방, 즉 Map에 저장된 모든 접속한 사람들에게 안내메시지를 전송하기 위한 메서드
* @param msg 전송할 메시지
*/
public void sendMessage(String msg){
Iterator<String> it = clients.keySet().iterator();
while (it.hasNext()) {
try {
String name = it.next(); // 대화명
// 해당 사용자에게 메시지 보내기
//getgetOutputStream 객체 만들어서 꺼냄
new DataOutputStream(
clients.get(name).getOutputStream()).writeUTF(msg);
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
//파라미터 2개라서 하나더 만듬 오버로딩
/**
* 대화방, 즉 Map에 저장된 모든 접속한 사람들에게 채팅 메시지 전송하기 위한 메서드
* @param msg 채팅메세지
* @param from 메시지 보낸 대화명
*/
public void sendMessage(String msg, String from){
sendMessage("[" +from + "]"+ msg);
}
/**
* 서버에서 클라이언트로부터 수신한 메세지를 처리하기 위한 클래스
* Inner클래스로 정의함.(Inner클래스에서는 부모클래스의 멤버들을 직접 접근할 수 있음)
* @author PC-10
*
*/
class ServerRecevier extends Thread{
private Socket socket;
private DataInputStream dis;
private String name;
public ServerRecevier(Socket socket) {
this.socket = socket;
try {
dis = new DataInputStream(socket.getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
try {
// 서버에서는 클라이언트가 보내온 최초의 메시지, 즉 대화명을 수신해야 한다.
name = dis.readUTF();
// 대화명을 받아서 다른 모든 클라이언트들에게 대화방 참여 메시지를 보낸다.
sendMessage("#" + name + "님이 입장했습니다.");
// 대화명을 사용하여 소켓객체를 Map에 저장한다.
clients.put(name, socket);
System.out.println("현재 서버 접속자 수는 " + clients.size() + "명 입니다.");
// 이 이후의 처리는 반복문으로 처리한다.
// 클라이언트가 보내온 메시지(대화내용)를 접속한 다른 모든 클라이언트
while (dis != null) {
//name 앞에 누구인지 출력하기 위한용
sendMessage(dis.readUTF(),name);
}
} catch (IOException ex) {
ex.printStackTrace();
}finally {
//이 부분이 실행된다는것은 클라이언트와 접속에 문제가 생겼다는 의미
// 그래서 접속종료 처리를 한다.
sendMessage(name + "님이 나가셧습니다.");
// Map에서 해당 사용자를 삭제한다.
clients.remove(name);
System.out.println("[" + socket.getInetAddress() + " : "
+ socket.getPort() + "] 에서 종료하였습니다.");
System.out.println("현재 서버 접속자 수는 " + clients.size() + "명 입니다.");
}
}
}
public static void main(String[] args) {
new MultiChatServer().serverStart();
}
}
MultiChatClient
더보기
package kr.or.ddit.tcp;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.Scanner;
public class MultiChatClient {
public void start() {
//소켓접속
Socket socket = null;
try {
socket = new Socket("192.168.144.~", 7777);
System.out.println("멀티챗 서버에 접속했습니다.");
//송신용 스레드 생성 및 실행
ClientSender sender = new ClientSender(socket);
sender.start();
//수신용 스레드 생성 및 실행
ClientReceiver receiver = new ClientReceiver(socket);
receiver.start();
} catch (IOException e) {
e.printStackTrace();
}
}
//메시지 전송을 위한 스레드 클래스
class ClientSender extends Thread{
private DataOutputStream dos;
private Scanner scan;
public ClientSender(Socket socket) {
scan = new Scanner(System.in);
try {
dos = new DataOutputStream(socket.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
try {
if(dos != null) { //대화명
//시작하자마자 자신을 대화명을 서버로 전송하기
System.out.println("대화명 >>");
dos.writeUTF(scan.nextLine());
}
while (dos != null) {
//이제부터는 일반 채팅메시지 전송하기
dos.writeUTF(scan.nextLine());
}
}catch (IOException e) {
e.printStackTrace();
}
}
}
//메시지 수신을 위한 스레드 클래스
class ClientReceiver extends Thread{
private DataInputStream dis;
public ClientReceiver(Socket socket) {
try {
dis = new DataInputStream(socket.getInputStream());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void run() {
try {
while (dis != null) {
//서버로부터 받은 메시지 콘솔에 출력하기
System.out.println(dis.readUTF());
}
}catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
new MultiChatClient().start();
}
}
'JAVA > NetWork' 카테고리의 다른 글
소켓통신 (1) | 2024.02.16 |
---|---|
Chat(1:1 채팅프로그램) (0) | 2024.02.16 |
TcpSocket (0) | 2024.02.15 |
URL클래스 (0) | 2024.02.14 |
URLConnection (0) | 2024.02.14 |