소켓(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 |