출처: https://bumcrush.tistory.com/182 [맑음때때로 여름]

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

			}
		}
	}
	
	
}

+ Recent posts