[TCP : chatPrj] TCP java 소켓 통신 간단한 1:1 채팅 프로그램

2022. 4. 4. 00:06· 프로젝트/mini project
목차
  1. 프로그램 정보
  2. JAVA 소켓 통신 학습 내용
  3. 자바 네트워크
  4. 소켓 프로그래밍

프로그램 정보

프로그램 개요 : JAVA 소켓 통신을 이용한 1:1 채팅 프로그램 개발

프로그램 언어 : JAVA

프로그램 기능 : 

  • 채팅 클라이언트 개발
  • 채팅 서버 개발

프로그램 코드 : https://github.com/smkim9202/MiniProject/tree/main/chatPrj

 

MiniProject/chatPrj at main · smkim9202/MiniProject

작은 실습 예제들. Contribute to smkim9202/MiniProject development by creating an account on GitHub.

github.com

 

JAVA 소켓 통신 학습 내용

자바 네트워크

TCP/IP 

  • TCP
    • TCP(Transmission Control Protocal) 두 시스템 간에 신뢰성 있는 데이터의 전송을 권장하는 프로토콜
    • 100개의 정보를 보내면 100개가 도달해야한다는 것을 보장하는 규약
    • e-mail, FTP, 웹(HTTP) 등이 TCP에서 동작하는 응용프로그램
  • IP
    • IP(Internet Protocol) 패킷 교환 네트워크에서 송신 호스트와 수신 호스트가 데이터를 주고 받는 것을 관장하는 프로토콜
    • TCP보다 하위 레벨 프로토콜
    • 주소를 보고 찾아 갈 수 있게 해주는 프로토콜
  • IP 주소
    • 네트워크 상에서 유일하게 식별 될 수 있는 컴퓨터 주소(4개의 숫자가 '.'으로 연결 되어 있음 => 192.156.11.15)
    • 숫자로 된 주소는 기억하기 어려우므로 문자열로 구성된 도메인 이름으로 바꿔 사용(www.nave.com)
    • DNS(Domain Name Server) => 문자열로 구성된 도메인 이름을 숫자로 구성 된 IP 주소로 자동 변환
    • 현재는 32비트의 IP 버전 4(IPv4) 사용 중이지만 주소 고갈로 인해 128비트의 IP 버전 6(IPv6)이 점점 사용되는 추세
    • 네트워크 상의 컴퓨터 또는 시스템을 식별하는 주소
  • PORT
    • 컴퓨터가 하나 이상의 역할을 하기 위해 포트를 열어서 사용(web 80, DB 1500 ....)
    • 통신하는 프로그램 간에 가상의 연결단인 포트 생성 => 포트 번호를 이용하여 통신할 응용프로그램 식별
    • 모든 응용프로그램은 하나 이상의 포트 생성 가능 => 포트를 이용하여 상대방 응용프로그램과 데이터 교환
    • 잘 알려진 포트(well-know ports)로는 0~1023 사이의 포트 번호가 있음 => 텔넷 23, HTTP 80, FTP 21
    • 개발자는 잘 알려진 포트 번호는 사용하지 않는 것이 좋음(충돌 가능성 있기 때문)
  • URL을 이용한 웹 프로그래밍
    • URL(Uniform Resource Locator)은 인터넷 상의 리소스에 대한 주소
    • URL 구조
      • 프로토콜 식별자(protocol identifier)://자원 이름(resource name)
      • http://www.naver.com/
  • 자원 이름(resource name)
    • 사용되는 프로토콜에 따라서 그 구성이 달라짐
      • http:호스트이름/파일이름:포트번호(8080)
      • https:호스트이름/파일이름:포트번호(443)

 

자바의 URL 클래스

  • java.net 패키지에 포함
  • 웹 상의 자원을 지정하는 URL을 나타냄

URL 객체 

  • URL(String spec) : 문자열이 지정하는 자원에 대한 URL 객체를 생성
  • URL(String protocol, String host, int port, String file) : 프로토콜 식별자, 호스트 주소, 포트 번호, 파일 이름이 지정하는 자원에 대한 URL 객체 생성
  • URL(String protocol, String host, String file) : 프로토콜 식별자, 호스트 주소, 파일 이름이 지정하는 자원에 대한 URL 객체 생성
  • URL(URL context, String spec) : URL 객체 context에 대한 상대 경로가 지정하는 자원에 대한 URL 객체 생성

자바의 URL 클래스의 주요 메소드

  • Object getContent() : URL의 컨텐트를 반환
  • String getFile() : URL 주소의 파일 이름 반환
  • String getHost() : URL 주소의 호스트 이름 반환
  • String getPath() : URL 주소의 경로 부분 반환
  • int getPort() : URL 주소의 포트 번호 반환
  • int getLocalPort() : 소켓이 연결된 로컬 포트 번호 반환
  • int getPort() : 소켓이 연결한 서버의 포트 번호 반환
  • inputStream openStream() : URL에 대해 연결을 설정하고 이 연결로부터 입력을 받을 수 있는 InputStream 객체 반환
  • URLConnection openConnection() : URL 주소의 원격 객체에 접속한 뒤 통신 할 수 있는 URLConnection 객체 리턴

자바의 URL 객체 생성 방법

  • 절대 경로로 URL 객체 생성
    • URL homePage = new URL("http://news.hankooki.com");
  • 상대 경로로 URL 객체 생성 : 잘못된 주소의 URL 입력시 MalformedURLException 예외 발생
    • URL opinion = new URL(homePage, "opinion/editorial.htm");
  • URL 객체에서 데이터 읽기
    • openStream() 메소드로 스트림 생성해서 URL 객체가 가리키는 주소에서 데이터를 가져옴
    • openStream()이 리턴하는 InputStream 객체를 이용하여 일반 스트림 입력을 수행

URL 객체 예제

package natwork;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;

public class URLRead {
	public static void main(String[] args) {
		try {
			//네트워크 세계
			URL url = new URL("https://www.naver.com/");
			BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()));
			//자바의 세계		
			String line;
			while((line = br.readLine()) != null) {
				System.out.println(line);
			}

			br.close();

		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}		
	}
}

 

URLConnection 클래스

  • 주어진 원격지의 주소 URL에 네트워크 접속 후 데이터를 보내거나 받을 수 있도록 하는 기능

URLConnection 클래스의 주요 메소드

  • abstract void connect() : URL에 의해 참조되는 외부 리소스와 통신 연결 설정
  • Object getContent() : URL 연결에서 컨텐트를 가져옴
  • String getContentEncoding() : 컨텐트 인코딩 필드를 반환
  • int getContentLength() : 컨텐트 길이 필드 반환
  • String getContentType() : 컨텐트 타입 필드 반환
  • boolean getDoInput() : URLConnection 객체의 doInput 필드 값 반환
  • boolean getDoOutput() : URLConnection 객체의 doOutput 필드 값 반환
  • InputStream getInputStream() : 설정된 연결에서 데이터를 읽을 입력 스트림 반환
  • OuputStream getOutputStream() : 설정된 연결로 데이터를 출력할 출력 스트림 반환
  • URL getURL() : URLConnection 객체의 URL 필드 값 반환
  • void setDoInput(boolean doInput) : URLConnection 객체의 doInput 필드 값 설정
  • void setDoOutput(boolan doOutput) : URLConnection 객체의 doOutput 필드 값 설정

URL 객체 생성 방법

  • URL.openConnection() 이용
URL aURL = new URL("https://www.naver.com/");
URLConnection uc = aURL.openConnection(); // 원격지와 연결한다.
  • URLConnection 생성자 이용 : 연결하기 전 여러가지 인자들과 요청과 관련된 속성들 설정 가능
URL aURL = new URL("https://www.naver.com/");
URLConnection uc = new URLConnection(aURL);
uc.connect(); //원격지와 연결한다.

URLConnection을 이용하여 원격지로 데이터 보내기

  • URLConnection 객체에서 데이터 쓰기
    • 웹 서버에 데이터를 요청하여 읽어올 때 주로 HTTP GET 사용
    • 웹 서버에 데이터를 요청 할 때 같이 처리 될 데이터를 보낼 때 HTTP POST 사용 
    • URLConnection 객체는 HTTP POST 방식으로 서버에 데이터 전송

HTTP POST 사례

  • 회원가입시 성과 이름을 입력하는 필드가 폼(form)
  • 필드에 데이터를 입력한 후 전송 버튼을 누르면 웹 서버로 데이터를 전송해야 하는데 이 데이터를 보내는 방법

웹 서버에 데이터를 보내기 위해서 필요한 단계

  1. URL 생성
  2. URL 객체에서 URLConnection 객체를 얻어온다.
  3. setDoOutput() 메소드로 doOuput 필드를 true로 설정
  4. connect() 메소드로 연결 설정
  5. 연결에서 출력 스트림을 얻어 온다.
  6. 출력 스트림에 데이터를 출력
  7. 출력 스트림을 닫는다.
package natwork;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;

public class URLConnectionWriter {

	public static void main(String[] args) {
		try {
			//POST가 가능한 사이트 URL 객체 생성
			URL aURL = new URL("");
			
			//URL 객체에서 URLConnection 객체 생성
			URLConnection uc = aURL.openConnection();
	
			//출력 모드 설정
			uc.setDoOutput(true);
			
			//출력 스트림 설정
			OutputStreamWriter out = new OutputStreamWriter(uc.getOutputStream());
			
			//서버에 데이터 보내기
			out.write("fname=Kitea&lname=Hwang");
			out.close();
			//입력 스트림 생성
			BufferedReader in = new BufferedReader(new InputStreamReader(uc.getInputStream())); 
			
			String inputLine;
			
			while((inputLine = in.readLine()) != null) //한행 씩 읽음
				System.out.println(inputLine);
				in.close();
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}

 

 

소켓 프로그래밍

소켓(socket) 

  • 네트워크 상에서 수행되는 두 프로그램 간의 양방향 통신 링크의 한쪽 끝 단을 의미
  • 특정 포트 번호와 연결되어 있음(TCP에서 데이터를 보낼 응용프로그램을 식별 할 수 있음)
  • 자바에서의 데이터 통신 시 소켓 사용
  • 소켓 종류 : 서버 소켓, 클라이언트 소켓

소켓을 이용한 서버 클라인트 통신 프로그램의 구조

클라이언트 소켓 =접속=> 서버 소켓 => 소켓 생성 => 소켓과 클라이언트끼리 소통

  1. 클라이언트 소켓이 지정된 IP주소와 포트번호에 맞는 서버 소켓에 접속
  2. 서버 접속 시 소켓이 생성
  3. 소켓과 클라이언트과 소통

Socket 클래스

  • 클라이언트 소켓에 사용되는 클래스
  • java.net 패키지에 포함
  • 주요 생성자
    • Socket(IntAddress address, int port) : 소켓을 생성하여 지정된 IP 주소와 포트 번호에 연결
    • Socket(String host, int port) : 소켓을 생성하여 지정된 호스트와 포트 번호에 연결. 호스트 이름이 null인 경우는 루프백(loopback) 주소로 가정
  • 주요 메소드
    • void close() : 소켓을 닫음
    • void connect(SocketAdress endpoint) : 소켓을 서버에 연결
    • InetAddress getInetAddress()
    • InputStream getInputStream() : 소켓에 대한 입력 스트림 반환
    • InetAddress getLocalAddress()
    • int getLocalPort()
    • int getPort()
    • OutputStream getOutputStream() : 소켓에 대한 출력 스트림 반환

소켓 생성, 서버 접속, 입출력 스트림 생성

  1. 클라이언트 소켓 생성 및 서버에 접속 : Socket 객체가 생성되면 곧 바로 IP주소로 자동 접속
  • Socket clientSocket = new Socket("IP", 포트번호);

2. 네트워크 입출력 스트림 생성 : 일반 스트림을 입출력 하는 방식과 동일

  • BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
    BufferedWriter out = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));

3. 서버로 데이터 전송 : flush()를 호출하면 스트림 속에 데이터를 남기지 않고 모두 전송

  • out.write("hello"+"\n");
    out.flush();

4. 서버로부터 데이터 수신

  • int x = in.read(); //서버로부터 한 개의 문자 수신
    String line = in.readline(); //서버로부터 한 행의 문자열 수신

5. 네트워크 접속 종료

  • clientSocket.close();

ServerSocket 클래스, 서버 소켓

  • 서버 소켓에 사용되는 클래스
  • java.net 패키지에 포함
  • 주요 생성자
    • ServerSocket(int port) : 소켓을 생성하여 지정된 포트 번호에 연결
  • 주요 메소드
    • Socket accept() : 연결 요청을 기다리다 연결 요청이 들어오면 수락하고 새 Socket 객체를 반환
    • void close()
    • InetAddress getInetAddress()
    • int getLocalPort()
    • boolean isBound()
    • boolean isClosed()
    • void setSoTimeout(int timeout) 

 

클라이언트와 서버

클라이언트와 서버 연결

  1. 서버는 서버 소켓으로 들어오는 연결 요청을 기다림 (서버 - 포트 - listen)
  2. 클라이언트가 서버에 연결 요청(클라이언트 - 포트 ==연결요청==> listen - 포트 - 서버)
  3. 서버가 연결 요청 수락, 새로운 소켓 생성 후 클라이언트와 연결(새로운 소켓 - 서버포트 <==연결==> 클라이언트포트)

서버소켓 생성, 클라이언트 접속, 입출력 스트림 생성

1. 서버 소켓 생성 : 이미 사용 중인 포트 번호 지정 시 오류 발생 주의

  • ServerSocket serverSocket = new ServerSocket(포트번호);

2. 클라이언트로부터 접속 기다림 : accept() 메소드는 연결 요청이 오면 새로운 Socket 객체 반환

  • 서버에서 클라이언트와의 데이터 통신은 새로 만들어진 Socket 객체를 통해 이루어짐
  • Socket socket = serverSocket.accept();

3. 네트워크 입출력 스트림 생성 : 일반 스트림을 입출력 하는 방식과 동일하게 네트워크 데이터 입출력

  • accept() 메소드에서 얻은 Socket 객체의 getInputStream()과 getOutputStream()메소드를 이용하여 데이터 스트림 생성
  • BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));

클라이언트로 데이터 송수신

1. 클라이언트로부터 데이터 수신

  • int x = in.read(); // 클라이언트로부터 한 개의 문자 수신
  • String line = in.readline(); //클라이언트로부터 한 행의 문자열 수신

2. 클라이언트로 데이터 전송

  • out.write("Hi"+"\n")
  • out.flush() //스트림 속에 데이터 남기지 말고 모두 전송

3. 네트워크 접속 종료

  • socket.close();

4. 서버 응용프로그램 종료 : 더 이상 클라이언트의 접속을 받지 않고 서버 응용 프로그램을 종료하고자 하는 경우

  • serverSocket.close();

 

소켓을 이용한 클라이언트/서버 채팅

간단한 채팅 프로그램 예제(1:1 채팅 하는 간단한 예제)

기능정리

  • 서버와 클라이언트 간의 메시지 구분을 위해 서버는 메시지 앞에 "서버>"를 접두어로 붙여 메시지를 전송한다.
  • 서버와 클라이언트가 번갈아 가면서 메시지 전송 및 수신
  • 클라이언트가 bye를 보내면 프로그램 종료

서버 프로그램

1. 서버 소켓 생성

  • 시스템에서 사용되지 않는 포트 번호로 서버 소켓 생성
  • ServerSocket listener = new ServerSocket(포트번호);

2. 클라이언트 요청 대기

  • 클라이언트가 연결 요청이 올 때까지 소켓 기다림
  • 해당 포트 번호로 연결 요청이 오면 연결을 수락하고 새로운 소켓을 생성 후 새 소켓으로 클라이언트와 통신
  • 새로운 소켓의 포트 번호는 자동으로 할당

3. 클라이언트와 통신을 위한 입출력 스트림 생성

  • 스트림을 생성하여 클라이언트와 데이터 송수신
  • 데이터의 종류에 따라 바이트 스트림 또는 문자 스트림을 생성
  • 채팅과 같이 문자열을 송수신하는 경우는 문자 스트림 사용
  • 효율적인 입출력을 위하여 버퍼 스트림(Buffered Stream) 사용
  • BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));

4. 클라이언트의 데이터 수신

  • 스트림 생성 이후는 데이터 입력 받는 방법과 동일
  • 클라이언트에서 한 행의 문자열을 보내올 때까지 기다림
  • String inputMessage = in.readLine();

5. 클라이언트의 데이터 송신

  • 스트림 생성 이후는 일반 데이터를 출력하는 방법과 동일
  • 콘솔에서 입력 받은 문자열을 클라이언트로 송신
  • flush() 메소드로 스트림의 모든 데이터를 클라이언트로 송신
  • String outputMessage = stin.readLine();
    out.write("서버>" + outputMessage + "\n");
    out.flush();

6.연결 종료

  • 데이터 송수신이 끝나면 소켓 닫음
  • 소켓을 닫으면 소켓의 입출력 스트림도 같이 닫힘
  • 서버 소켓을 닫으면 클라이언트 연결 요청 받을 수 없음
  • socket.close();
    listener.close();

클라이언트 프로그램
1. 연결 요청 : 소켓생성(서버의 호스트 주소, 서버가 연결 요청을 모니터링하는 포트 번호로 소켓 생성)

  • socket = new Socket("localhost", 포트번호); // 동일한 시스템에서 동작하기 때문에 IP주소는 localhost로 지정

2. 클라이언트와 통신을 위한 입출력 스트림 생성

  • 스트림을 생성하여 서버와 데이터 송수신
  • 데이터 종류에 따라 바이트 스트림 또는 문자 스트림 사용
  • 채팅과 같이 문자열을 송수신하는 경우는 문자 스트림 사용
  • 효율적 입출력을 위하여 버퍼 스트림(Buffered Stream) 사용
  • BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));

3. 서버에 데이터 송신

  • 스트림 생성 이후는 데이터 출력 방법과 동일
  • 콘솔에서 입력 받은 문자열을 서버로 송신
  • flush() 메소드로 스트림의 모든 데이터를 서버로 송신
  • String outputMessage = stin.readLine();
    out.write("클라이언트>"+outputMessage+"\n");
    out.flush();

4. 클라이언트의 데이터 수신

  • 스트림 생성 이후는 데이터 입력 방법과 동일
  • 서버에서 한 행의 문자열을 보내 올 때까지 기다림
  • String inputMessage = in.readLine();

5. 연결 종료

  • 데이터의 송수신이 끝나면 소켓 닫아야 함
  • 소켓을 닫으면 소켓의 입출력 스트림도 같이 닫힘
  • socket.close();

 

간단한 1:1채팅 프로그램 예제 코드

서버

package chat;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;


public class ServerEx {

	public static void main(String[] args) {
		ServerSocket server = null;
		Socket socket = null;
		BufferedReader in = null;
		BufferedWriter out = null;
		Scanner sc = new Scanner(System.in);
		
		try {
			server = new ServerSocket(9999);
			System.out.println("서버시작 : 연결 대기중....");
			
			socket = server.accept();
			System.out.println("클라이언트와 연결 됨");
			
			in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
			
			while(true) {
				String inMsg = in.readLine();
				if(inMsg.equalsIgnoreCase("bye")) {
					System.out.println("클라이언트가 나감");
					break;
				}
				//정상 메시지인 경우
				System.out.println("클라이언트 : "+ inMsg);
				
				System.out.println("보내기 >>");
				String outMsg = sc.nextLine();
				out.write(outMsg + "\n");
				out.flush();				
			}
			
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			try {
				sc.close();
				out.close();
				in.close();
				socket.close();
				server.close();
			}catch(IOException e) {
				e.printStackTrace();
			}
		}
		

	}

}

 

클라이언트

package chat;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.Scanner;


public class ClientEx {

	public static void main(String[] args) {
		Socket socket = null;
		BufferedReader in = null;
		BufferedWriter out = null;
		Scanner sc = new Scanner(System.in);
		
		try {
			socket = new Socket("localhost", 9999);
			System.out.println("서버에 연결 됨");
			
			in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
			
			while(true) {
				System.out.println("보내기>>");
				String outMsg = sc.nextLine();
				
				if(outMsg.equalsIgnoreCase("bye")) {
					out.write(outMsg + "\n");
					out.flush();
					System.out.println("접속 종료!!!");
					break;
				}
				//정상 메시지인 경우
				out.write(outMsg + "\n");
				out.flush();		
				
				String inMsg = in.readLine();
				System.out.println("서버>>" + inMsg);
			}
			
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			try {
				sc.close();
				out.close();
				in.close();
				socket.close();

			}catch(IOException e) {
				e.printStackTrace();
			}
		}
		

	}

}

'프로젝트 > mini project' 카테고리의 다른 글

[JSP MVC1 : GoGoTaiwan] JSP를 이용한 MVC1 패턴의 웹사이트  (0) 2021.12.04
[Frontend : MainPageExample] 웹사이트 Main 페이지  (0) 2021.10.30
[Frontend : DropDownExample] 드롭다운형식 메뉴바  (0) 2021.10.18
[Frontend : CodingStudy] Frontend 웹페이지 + 깃헙 웹 호스팅  (0) 2021.01.04
  1. 프로그램 정보
  2. JAVA 소켓 통신 학습 내용
  3. 자바 네트워크
  4. 소켓 프로그래밍
'프로젝트/mini project' 카테고리의 다른 글
  • [JSP MVC1 : GoGoTaiwan] JSP를 이용한 MVC1 패턴의 웹사이트
  • [Frontend : MainPageExample] 웹사이트 Main 페이지
  • [Frontend : DropDownExample] 드롭다운형식 메뉴바
  • [Frontend : CodingStudy] Frontend 웹페이지 + 깃헙 웹 호스팅
개발원슝이
개발원슝이
꾸준히 개발공부를 합니다.
개발원슝이
꾸준히 개발슝이
개발원슝이
전체
오늘
어제
  • ALL (236)
    • 프로젝트 (34)
      • clone coding (19)
      • mini project (5)
      • Team project(with KIC) (10)
    • 문제 (37)
      • 백준 (7)
      • 프로그래머스 (14)
      • 정보처리기사실기 (16)
    • 설치 (9)
    • 개발 기초 (12)
    • 프로그래밍언어 (120)
      • HTML (16)
      • CSS (17)
      • JavaScript (18)
      • JAVA (13)
      • JSP (10)
      • Python (22)
      • C언어 (24)
    • 프레임워크 (6)
      • Spring (3)
      • Django (3)
    • DB (2)
      • MySQL (2)
    • AWS (1)
    • 오류 (2)
    • 이것저것 (6)
    • 전공자 개발 (2)
    • 비전공자 개발 (5)

블로그 메뉴

  • 네이버블로그(강의노트)
  • GitHub
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 파이썬공부
  • javascript
  • 인프런
  • 따배씨
  • 점프 투 파이썬
  • 홍정모의 따라하며 배우는 C언어
  • 생활코딩
  • 백준
  • 코딩테스트
  • 홍정모교수님

최근 댓글

최근 글

hELLO · Designed By 정상우.v4.2.2
개발원슝이
[TCP : chatPrj] TCP java 소켓 통신 간단한 1:1 채팅 프로그램
상단으로

티스토리툴바

개인정보

  • 티스토리 홈
  • 포럼
  • 로그인

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.