소켓(Socket)이란?
소켓은 TCP를 위한 구조이다. TCP를 사용하여 응용 프로그램끼리 통신을 하기 위해서는 먼저 연결을 하여야 하는데 연결을 하기 위해서느 연결 끝점(End point)가 있어야 한다. 이 연결끝점이 바로 Socket이다.
Socket 클래스
생성자 | 설명 |
Socket (String host, int port) | 호스트 이름이 host이고 포트 번호가 port인 새로운 소켓을 생성한다 |
Socket (InetAddress address, int port) | InetAddress에 기술된 주소로 새로운 소켓을 생성한다 |
메소드 | 설명 |
InputStream getInputStream() | 소켓이 사용하는 입력 스트림을 반환한다 |
OutputStream getOutputStream() | 소켓이 사용하는 출력 스트림을 반환한다 |
Inetaddress getInetAddress() | 소켓이 연결되어 있는 인터넷 주소를 반환한다 |
public int getLocalPort() | 소켓이 연결되어 있는 포트 번호를 반환한다 |
public int getPort() | 원격 컴퓨터의 포트번호를 반환한다 |
pbulic InetAddress getLocalAddress() | 소케싱 연결되어 있는 인터넷 주소를 반환한다 |
ServerSocket 클래스
생성자 | 설명 |
public ServerSocket(int port) throws IOException | 포트번호 Port에 대해 ServerSocket의 새로운 인스턴스를 만든다. 포트번호 0은 비어있는 포트번호를 사용한다는 의미이다. queue는 서버가 받을 수 있는 입력 연결의 개수를 의미한다. (디폴트는 50연결이다) address는 컴퓨터의 인터넷 주소를 나타낸다. |
public ServerSocket(int port, int queue) throws IOException | |
public ServerSocket(int port, int queue, InetAddress address ) throws IOException |
메소드 | 설명 |
public socket accept() | 접속요청을 받는다 |
public void close() | ServerSocket을 닫는다 |
public Inetaddress getInetAddress() | 소켓이 연결되어 있는 인터넷 주소를 반환한다 |
public int getSoTimeout() | 소켓에 대한 타임아웃값을 밀리 초로 반환하거나 설정한다. |
소켓클래스를 이용한 채팅방
서버)
package network;
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
public class TCPIPChatMultichatServer {
// 접속 사용자 정보를 저장 : 메세지를 전체에게 보내기 위해서
// 저장정보 : name, OutputStream
// Map<String, Object>로 저장
HashMap<String, Object> clients;
public TCPIPChatMultichatServer() {
clients = new HashMap<String, Object>();
Collections.synchronizedMap(clients); // 스레드 동기화에 안전한 상태로 해주는메서드
}
public void start() throws IOException {
// Server Socket 생성
// 사용자의 요청이 있으면 Socket 생성해서 연결 > Clients 사용자 정보를 저장
// 연결 > Clients 사용자 정보를 저장 스레드로 처리
ServerSocket serverSocket = new ServerSocket(7777);
System.out.println("Chatting Server Start!");
Socket socket = null;
while(true) {
// 요청이 들어올 때까지 대기 하다가 요청이 들어오면 새로운 소켓을 생성해서 반환
socket = serverSocket.accept();
// map에 정보저장, 접속한 사람들에게 메세지를 전송
System.out.println("["+socket.getInetAddress()+socket.getPort()+"] 사용자 접속");
ServerReceiver receiver = new ServerReceiver(socket);
receiver.start();
}
}
void SendToAll(String msg) {
// 일괄처리 - Map은 순서가 없다 - Map이 가지고 있는 key를 Set으로 만든다.
Set<String> keys = clients.keySet();
Iterator<String> itr = keys.iterator();
while (itr.hasNext()) {
DataOutputStream out = (DataOutputStream) clients.get(itr.next()); // 키값가져오기
try {
out.writeUTF(msg);
} catch (IOException e) {
e.printStackTrace();
}
}
}
// 내부클래스 : 데이터 받아서 저장, 메시지 전체 발송
private class ServerReceiver extends Thread {
// Socket, InputStream, OutputStream
Socket socket;
DataOutputStream out;
DataInputStream in;
public ServerReceiver(Socket socket) {
this.socket = socket;
try {
in = new DataInputStream(socket.getInputStream());
out = new DataOutputStream(socket.getOutputStream());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void run() {
String name=null; // 접속한 사용자 이름
try {
name= in.readUTF(); // 이름을 스트림을 통해 받는다
clients.put(name, out); // map에 사용자 정보 저장
SendToAll(">>>>>>>>>> " +name+"님이 접속하셨습니다.");// 내부클래스에서는 외부 클래스의 멤버를 참조할 수 있다.
while(in !=null ) {
SendToAll(in.readUTF());
}
} catch (IOException e) {
e.printStackTrace();
} finally {
clients.remove(name);
System.out.println(name+"님이 나가셨습니다.");
}
}
}
public static void main(String[] args) throws IOException {
new TCPIPChatMultichatServer().start();
}
}
클라이언트)
package network;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
import thread.threadMain;
public class TCPIPMulitiChatClient {
public static void main(String[] args) {
String serverIp = "192.168.0.32"; // localhost > 호스트자신의 주소
//Socket연결
try {
Socket socket = new Socket(serverIp, 7777);
// 메세지를 받는 스레드
Thread receiver = new ClientReceiver(socket);
// 메세지를 보내는 스레드
Thread sender = new ClientSenderThread(socket, "포그바");
sender.start();
receiver.start();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
class ClientSenderThread extends Thread{
// 보내기 스레드는 Socket, OutputStream, name도 필요하다.
Socket socket;
DataOutputStream out;
String name;
public ClientSenderThread(Socket s, String name) {
this.socket = s;
try {
out = new DataOutputStream(s.getOutputStream());
this.name = name;
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
Scanner sc = new Scanner(System.in);
try {
// 접속하면 이름을 서버에 전송
if(out != null) {
out.writeUTF(name);
}
while(out!=null) {
out.writeUTF("["+name+"]"+sc.nextLine());
}
}catch (IOException e) {
e.printStackTrace();
}
}
}
class ClientReceiver extends Thread {
// 메세지를 받아서 콘솔에 출력
// Socket, InputStream, 필요
Socket socket;
DataInputStream in;
public ClientReceiver(Socket socket) {
this.socket = socket;
try {
in = new DataInputStream(socket.getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
while (in != null){
try {
System.out.println(in.readUTF());
} catch (IOException e) {
}
}
}
}
'JAVA > basic' 카테고리의 다른 글
[JDBC] 자바와 데이터 베이스(MYSQL) 연결하기 (0) | 2020.11.19 |
---|---|
[JAVA] JDBC 라이브러리 가져오기 - 커넥트 (0) | 2020.11.19 |
[JDBC] 자바와 데이터 베이스(Oracle SQL) 연결하기 (0) | 2020.11.18 |
[ 네트워크 ] URL (0) | 2020.10.28 |
스레드 / 쓰레드 / thread (0) | 2020.10.27 |
[ 입출력 ] 버퍼 스트림 (0) | 2020.10.26 |
[ 입출력 ] File (0) | 2020.10.26 |