1. 짚고가야 할 주요 용어
- 컴퓨터 Network은 서로 다른 장소에 있는 컴퓨터 시스템들을 서로 연결하는 데이터 통신 시스템을 말한다.
(2) 프로토콜(PROTOCOL)이란 ?
- 통신할 때의 데이터를 구분 하기 위한 꼬리표(통신규약 - 언어)
(1) TCP/IP의 개념 (Transmission Control Protocol/Internet Protocol)
- 통신 프로토콜 혹은 통신 규약. 인터넷에서 사용하는 기본적인 통신 프로토콜이며 인트라넷이나 엑스트라넷과 같은 사설 망에서도 사용이 가능함. 사용자가 인터넷에 접속하기 위해 자신의 컴퓨터를 설정할 때 TCP/IP 프로그램이 설치되며, 이를 통하여 역시 같은 TCP/IP 프로토콜을 쓰고 있는 다른 컴퓨터 사용자와 메시지를 주고받거나, 또는 정보를 얻을 수 있게 됨
- TCP/IP프로그램은 2개의 계층으로 이루어짐.. 상위계층인 TCP는 메시지나 파일들을 좀더 작은 패킷으로 나누어 인터넷을 통해 전송하는 일과, 수신된 패킷들을 원래의 메시지로 재조립하는 일 수행. 하위계층인 IP는 각 패킷에 주소를 붙여주어 패킷들이 목적지에 정확하게 도달할 수 있도록 함. 때문에 한 메시지가 여러 개의 패킷으로 나뉘어진 경우 각 패킷들은 서로 다른 경로를 통해 전달될 수 있으며, 그것들은 최종 목적지에서 재조립될 수 있음.
- TCP/IP는 통신하는데 있어 클라이언트/서버 모델을 사용하여 점대점(点對点) 통신을 수행. 즉, 각 통신이 네트워크 상의 한 점(또는 호스트 컴퓨터)에서 시작되어, 다른 점(다른 호스트 컴퓨터)로 전달이 되는 것
클라이언트 - 서버 모델 컴퓨터 사용자(클라이언트)의 요구에 대응하여, 네트워크상의 다른 컴퓨터(서버)가 웹 페이지를 보내는 방식. |
(2) IP address / IP 주소
- 인터넷 주소. 인터넷상에서 효율적 신호를 전달하기 위하여 만든 주소. 네트워크번호 및 호스트번호로 되어 있기 때문에 IP주소를 통해 해당 호스트가 속한 네트워크와 개별 호스트를 식별할 수 있음.
- version4와 version6 두 가지 버전이 있으며 version4 는 32비트. version6 는 64비트임
1) IPv4 : network class / 네트워크 클래스
- IPv4에서 ip주소를 분류하는 방식으로 A,B,C,D로 구분.
- XXX.000.000.000 에서 X에 해당하는 부분이 클래스에 따라 결정됨.
- IP주소는 클래스로 구분되어질 수 있으며 하나의 네트워크 망에 있는 모든 호스트들은 같은 앞부분을 가짐.
- 클래스 A는 7 비트의 netid와 24 비트의 hostid로 나뉘어 있으므로 하나의 네트웍에 216개보다 많은 호스트가 존재할 때 사용. 클래스 B는 28~216개 사이의 중간 크기 네트웍에서 사용. 클래스 C는 28 개 호스트 이하의 네트웍에서 사용.
- 국가별로 IP 주소를 할당 받는데 클래스 A는 대부분 선진국이 가지고 있음. 클래스 A에서 D로 갈수록 더 적은 수의 호스트를 할당하기 때문에 클래스 A로 갈 수록 ip주소를 분배하기 유리함.
2) IPv6 의 특징
①동시 사용 가능 : IPv6는 IPv4를 위하여 설계. IPv4나 IPv6 동시에 사용될 수 있음. 즉, 네트워크 상의 모든 호스트와 노드들은 모두 두 가지 등급의 IP 중 어느 것에 의해 형식화된 패킷이라도 처리할 수 있음.
②애니캐스트: IPv6는 유니캐스트 (하나의 호스트에서 다른 하나의 호스트로), 애니캐스트 (하나의 호스트에서 가까이 있는 여러 개의 호스트들로), 멀티캐스트 (하나의 호스트에서 다중 호스트들로) 등 3가지 형태의 주소에 관한 규칙을 가짐. 애니캐스트 주소의 도입은 하나의 메시지를 가까이 있는 여러 개의 게이트웨이 호스트들에게 보낼 수 있는 가능성과, 그들 중 누구라도 다른 사람에게 전달되는 패킷을 관리할 수 있는 아이디어를 제공. 애니캐스트 메시지들은 회선을 따라 이동하면서 라우팅 테이블을 수정하는데 사용될 수 있음. 특정한 흐름에 속해 있는 패킷들을 인식함으로써, 실시간으로 전달될 필요가 있는 멀티미디어 표현용 패킷들이 다른 고객들에 비하여 높은 품질의 서비스를 제공받을 수 있도록 할 수 있음.
③확장된 해더 : IPv6는 헤더가 확장됨으로서 선택사항들을 기술할 수 있으며, 이것은 수신지에서만 검색되므로 네트웍 속도가 전반적으로 빨라짐., 패킷의 출처 인증, 데이터 무결성의 보장 및 비밀의 보장 등을 위한 메커니즘을 지정할 수 있음.
3) IP해더의 구조
- Version(IP 프로토콜의 버전)-4비트
- Header Length(헤더의 길이)-4비트 : 한비트는 4바이트를 나타냄, 즉 5이면 5*4=20바이트
- Service Type(서비스 타입)-8비트 :라우터에 의한 처리방법
- Total Length(전제길이)-16비트 : 이 값이 16비트이므로 IP 데이터그램의 전체 길이는 2의 16승 즉 65536바이트로 제한.
- Identification(식별자)-16비트 : 한 데이터그램의 단편은 모두 같은 Identification을 갖게 됨. 한 데이터그램이 네트웍에 따라 다른 MTU(Maximum Transfer Unit) 때문에 예를 들어 열개로 쪼개지면 열개의 단편들은 모두 같은 값(Identification, 예:100)을 갖게 됨. 따라서 두개의 데이터 그램 단편이 서로 순서가 바뀌어 도착해도 재결합할 때 이를 이용해 데이터그램을 구분할 수 있게 됨
- Flags(플래그)-3비트 : 단편화 관련 정보. 첫번째 비트는 사용안함. 두번째 비트가 1이면 데이터그램을 더이상 단편화하면 안되고 세번째 비트가 1이면 데이터그램의 마지작 단편이 아니라는 것을 알림. 0이라면 마지막 단편이거나 유일한 단편의 의미.
- Flagmentation offset(단편화 옵셋) -13비트 : 전체 데이터그램 내에서 이 단편의 상대적 위치. 몇 번째 조각인지 표시.
- Time To Live(수명) - 8비트 : 라우터를 하나 건널 때마다 하나씩 줄어들어 0이 되면 폐기. 255까지 값을 가질 수 있음.
- Type(포로토콜 타입) - 8비트 : 전송계층(TCP계층)에서 사용될 프로토콜 번호. IP 계층의 서비스를 사용하는 상위 계층 프로토콜을 정의. 데이터그램이 캡슐화하는 4계층의 프로토콜이 ICMP인지 혹은 UDP, TCP, IGMP 중 어떤 것인지 표시.
- Header Checksum(검사합) - 16비트 : 전송 중 오류에 대한 검사.
- Source Address(발신지 주소) - 32비트 : 데이터그램 발신지의 IP주소
- Destination Address(목적지 주소) - 32비트 : 데이터 그램의 목적지의 IP주소
- IP Options(네트워크 관리)
- Padding : IP OPTIONS가 32bit를 채우지 못할 경우 0을 채워 넣음.
(3) UDP(User Datagram Protocol)
- IP를 사용하는 네트워크 내에서 컴퓨터들 간에 메시지들이 교환될 때 제한된 서비스만을 제공하는 통신 프로토콜. 교환해야 할 데이터가 매우 적은 네트워크 응용프로그램들이 처리시간 단축을 위해 사용 함.
- TCP와 유사점 : 한 컴퓨터에서 다른 컴퓨터로 데이터그램이라고 불리는 실제 데이터 단위를 받기 위해 IP를 사용. TCP의 대안으로 사용되며 IP와 함께 쓰일 때에는 UDP/IP라고 표현. UDP는 IP 계층에서 제공되지 않는 두 개의 서비스를 제공: 다른 사용자 요청을 구분하기 위한 포트 번호, 도착한 데이터의 손상여부를 확인하기 위한 체크섬 기능
- TCP와 차이점 : 메시지를 패킷(데이터그램)으로 나누고, 반대편에서 재조립하는 등의 서비스는 제공하지 않으며, 특히 도착하는 데이터 패킷들의 순서를 제공하지 않음. 즉, UDP를 사용하는 응용프로그램은, 전체 메시지가 올바른 순서로 도착했는지에 대해 확인할 수 있어야 함.
(4 )ARP (Address Resolution Protocol) ; 주소결정 프로토콜
- IP 네트워크 상에서 IP 주소를 물리적 네트워크 주소(이더넷 또는 토큰링의 48 bits 네트워크 카드 주소 : Mac address)로 대응시키기 위해 사용되는 프로토콜.
예를 들어, IP 호스트 A가 IP 호스트 B에게 IP 패킷을 전송고자 할 때 IP 호스트 B의 물리적 네트웍 주소를 모르는 경우, ARP 프로토콜을 사용하여 목적지 IP 주소 B와 브로드캐스팅 물리적 네트웍 주소 FFFFFFFFFFFF를 가지는 ARP 패킷을 네트웍 상에 전송한다. IP호스트 B는 자신의 IP 주소가 목적지에 있는 ARP 패킷을 수신하면 자신의 물리적 네트웍 주소를 A에게 응답한다. 이와 같은 방식으로 수집된 IP 주소와 이에 해당하는 물리적 네트웍 주소 정보는 각 IP 호스트의 ARP 캐시라 불리는 메모리에 테이블 형태로 저장된 후 다음 패킷 전송시에 다시 사용된다. ARP와는 역으로, IP 호스트가 자신의 물리 네트웍 주소는 알지만 IP 주소를 모르는 경우, 서버로부터 IP주소를 요청하기 위해서는 RARP를 사용한다. |
(5) ICP(Internet Cache Protocol)
- 프럭시서버가 원하는 내용을 검색하기 위해 인터넷에 가지 않아도 되도록, 다른 프럭시 서버에게 캐시되어 있는 웹페이지를 질의하는데 사용되는 프로토콜
(3) PORT란?
- 컴퓨터의 출입구(랜선)에 들어있는 통신 통로 (65000 여개)
(4) 패킷이란?
- 데이터를 전송하기 위한 최소 전송단위 (크기가 다를 수 있다)
(5) URL 이란?
- Uniform Resource Locator.
- 네트웍상의 리소스(자원)의 위치 정보
(6) 통신이란?
- 네트웍상의 컴퓨터의 데이터 교류 (Give & Take)
(7) OSI 7Layer란?
- 두 대 이상의 컴퓨터 사이의 통신 단계를 7가지로 나누어 놓은 것 (논리적인 단위)
ISO의 OSI 7 Layer
1980년대초 통신 기술의 발달과 개인용 컴퓨터의 보급으로 이기종 컴퓨터간의 네트워크의 필요성이 절실하게 대두
되자 국제표준협회(ISO)는 OSI(Open System Interconnection, 개방 시스템 상호 연결) 7 Layer라는 새로운 네트워크 모델을 발표 했습니다. 이 모델은 서로 다른 컴퓨터 기기간에 네트워크를 형성할 수 있도록 규정한 네트워크 모델 표준안 입니다. 이 모델은 모든 통신 관련 시스템, 즉 각종 네트워크 장비 및 컴퓨터기기등에 동일하게 적용이 되는
개념이며 우리가 사용하고 접하는 모든 통신 관련 시스템은 이 OSI 7 Layer 범주에 속하게 됩니다.
이 OSI 참조 모델은 각 시스템의 하드웨어 및 소프트웨어 자원을 서로 다른 기능을 수행하는 7개의 계층으로 구분 했습니다..
7 계층 Application 응용 계층 |
프로토콜: DHCP,DNS,FTP,HTTP 서비스 제공 |
사용자가 네트워크에 접근 할 수 있도록 해주는 계층이다. 사용자 인터페이스,전자우편,데이터베이스 관리 등 서비스를 제공한다. 텔넷 HTTP,SSH,FTP 등을 들 수 있다. |
6 계층 Presentation 표현 계층 |
프로토콜: JPEG,MPEG,SMB,AFP 이해할 수 있는 포맷 변환. |
운영체계의 한 부분으로 입력 또는 출력되는 데이터를 하나의 표현 형태로 변환한다. 필요한 번역을 수행하여 두 장치가 일관되게 전송 데이터를 서로 이해할 수 있도록 한다. 제어코드나 문자 및 그래픽등의 확장자를 생각하면 쉽다. |
5 계층 Session 세션 계층 |
프로토콜: SSH,TLS 응용간의 질서 제어 |
통신 세션을 구성하는 계층으로 포트 연결이라고도 할 수 있다. 통신 장치 간의 상호작용을 설정하고 유지하며 동기화 한다. 사용자간의 포트연결이 유효한지 확인하고 설정한다. |
4 계층 Transport 전송 계층 |
프로토콜: TCP,UDP,ARP 장비:게이트웨이 |
전체 메시지를 발신지 대 목적지(종단 대 종단)간 제어와 에러를 관리한다. 패킷들의 전송이 유효한지 확인하고 실패한 패킷은 다시 보내는 등 신뢰성 있는 통신을 보장하며, 머리말에는 세그먼트가 포함된다 대표적인 프로토콜은 TCP |
3 계층 Network 네트워크 계층 |
프로토콜: IP,ICMP,IGMP 장비:라우터 |
다중 네트워크 링크에서 패킷을 발신지로 부터 목적지로 전달할 책임을 갖는다. 2계층은 노드 대 노드 전달을 감독하는 것이고 3계층은 각 패킷이 시작 시점에서 최종 목적지 까지 성공적이고 효과적으로 전달되도록 하며, 프로토콜은 ip |
2. 주요 클래스
(1) URL
<1> 기능 : URL 클래스를 이용하면 네트웍상의 접속한 컴퓨터의 프로토콜, 호스트, 포트번호, 파일등의 정보를 알 수 있다.
<2> 주요 메소드
- getProtocol()
- getHost()
- getPort()
- getFile()
- getPath()
* 참고하기 : 2012/09/06 - [Dev. 자바/API 및 이론] - [JAVA API] java.net.URL
URLTest1.java : 접속 페이지 정보 보기
import java.net.*;
// URL (Uniform Resource Location on the World Wide Web) 클래스
public class URLTest1
{
public static void main(String[] args)
{
try
{
URL url = new URL("http://news.media.daum.net/society/?nil_profile=g&nil_News=9");
p("url : " + url);
String protocol = url.getProtocol();
p("protocol : " + protocol);
String host = url.getHost();
p("host : " + host);
int port = url.getPort();
p("port : " + port);
/*
* port가 -1로 반환되는 것은 프로토콜에 해당하는
* 디폴트 포트로 접속이 일어난다는 것을 의미한다.
* <참고>
* 기본포트 (1 ~ 65536)
* - http : 80, smtp : 25, ftp : 21, telnet : 23, pop3 : 110, https : 443, time : 37
*/
String f = url.getFile();
p("접속 파일 : " + f);
String path = url.getPath();
p("경로 : " + path);
}
catch (MalformedURLException mue)
{
p("URL의 형식에 맞지 않습니다." + mue);
}
}
public static void p(String str)
{
System.out.println(str);
}
}
/*
* URL 클래스를 이용하면 네트웍상의 접속한 컴퓨터의
* 프로토콜, 호스트, 포트번호, 파일등의 정보를 알 수 있다.
*
*/
>> 결과 <<
url : http://news.media.daum.net/society/?nil_profile=g&nil_News=9
protocol : http
host : news.media.daum.net
port : -1
접속 파일 : /society/?nil_profile=g&nil_News=9
경로 : /society/
URLTest2.java : 페이지 소스보기
import java.net.*;
import java.io.*;
public class URLTest2
{
public static void main(String[] args)
{
try
{
URL url = new URL("http://www.naver.com");
InputStream is = url.openStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
FileWriter fw = new FileWriter(new File("index.html"));
String str = "";
while ((str = br.readLine()) != null)
{
fw.write(str + "\n");
System.out.println(str);
fw.flush();
}
}catch (MalformedURLException e)
{
e.printStackTrace();
}catch (IOException ie)
{
ie.printStackTrace();
}
}
}
>> 결과 <<
URLTest3.java : 그림 저장 하기
import java.io.*;
import java.net.*;
public class TestTest
{
public static void main(String[] args)
{
try
{
URL url = new URL("http://static.naver.net/www/u/2010/0611/nmms_215646753.gif");
InputStream is = url.openStream();
BufferedInputStream bis = new BufferedInputStream(is);
FileOutputStream fos = new FileOutputStream("test.gif");
BufferedOutputStream bos = new BufferedOutputStream(fos);
byte[] ba = new byte[100]; // 계란판
int n = 0; // 읽은 바이트 수를 반환
while ((n = bis.read(ba, 0, 100)) != -1)
{
bos.write(ba, 0, n);
bos.flush();
}
}catch (Exception e)
{
e.printStackTrace();
}
}
}
(2) URLConnection
<1> 기능 : 객체 생성시 URL의 자원과 연결이 되어지기 때문에 자원의 구체적인 Content정보를 알 수 있다.
<2> 용도 : Post방식으로 데이터를 먼저 보내고 그 결과를 받기 위해서는 URLConnection클래스를 이용해야 한다.
<3> 주요 메소드
- getContentType()
- getContentLength()
- getInputStream()
- getOutputStream()
(3) InetAddress
<1> 기능 : 네트웍 호스트에 대한 IP을 알아 낼 수 있다.
<2> 주요 메소드
- getByName()
- getHostName()
- getHostAddress()
- getLocalHost()
- getAllByName()
import java.net.*;
import java.io.*;
public class TestTest {
public static void main(String args[]) throws IOException{
InetAddress inetAddr = null;
InetAddress inetAddrArr[] = null;
try{
// 1. 로컬호스트 정보 알아오기
inetAddr = InetAddress.getLocalHost();
// 주소 출력
System.out.println("호스트 주소 : " + inetAddr.getHostAddress());
System.out.println("호스트 이름 : " + inetAddr.getHostName());
System.out.println("Canonical Host Name: " + inetAddr.getCanonicalHostName());
System.out.print("Is Any Local: " + inetAddr.isAnyLocalAddress());
System.out.print(" - Is Link Local: " + inetAddr.isLinkLocalAddress());
System.out.print(" - Is Loopback: " + inetAddr.isLoopbackAddress());
System.out.print(" - Is Multicast: " + inetAddr.isMulticastAddress());
System.out.println(" - Is Site Local: " + inetAddr.isSiteLocalAddress());
System.out.println("Is Reachable in 2 seconds: " + inetAddr.isReachable(2000));
System.out.println("================이름으로 주소 가져오기==================");
InetAddress naverAddr = inetAddr.getByName("www.naver.com");
System.out.println("호스트 주소 : " + naverAddr.getHostAddress());
System.out.println("호스트 이름 : " + naverAddr.getHostName() + "\n");
System.out.println("================호스트 주소 배열로 가져오기==================");
inetAddrArr = InetAddress.getAllByName("www.daum.net");
for(int i =0; i < inetAddrArr.length; i++){
System.out.println(" [ "+i+" ] " + inetAddrArr[i].getHostAddress());
}
}catch(UnknownHostException e){
e.printStackTrace();
}
}
}
3. 통신방식
(1) TCP기반의 Socket통신
<1> 연결 지향 통신 방식
<2> 전화에 비유 (신뢰적)
<3> ServerSocket, Socket 을 이용해서 프로그램
<4> 프로그램 절차
<<Server 측>> <<Client 측>>
ServerSocket ss
ss.accept()
Socket s <--------------> Socket s
IO 객체를 이용
<5> 사용예 : 채팅, 실시간 데이터 전송, 메신져, 네트웍 게임
(2) UDP방식의 DatagramSocket 통신
<1> 비연결 지향 통신 방식
<2> 편지에 비유 (비신뢰적)
<3> DatagramSocket, DatagramPacket 을 이용해서 프로그램
<4> 프로그램 절차
<<Server 측>> <<Client 측>>
DatagramSocket ds DatagramSocket ds
DatagramPacket dp DatagramPacket dp
ds.receive(dp); <----------------- ds.send(dp);
<5> 사용예 : 인터넷 방송
서버 프로그램
package com.hkp.socket;
import java.io.*;
import java.net.*;
import java.util.*;
public class OnetoMulServer extends Thread
{
ServerSocket ss;
Socket s;
BufferedReader br_in;
OneClientManager cm;
Thread th;
String msg_server;
public OnetoMulServer()
{
try
{
ss = new ServerSocket(8888);
p("클라이언트의 접속을 기다리고 있습니다.");
p("━━━━━━━━━━━━━━━━━━━━━━━━━━");
p("명령어 안내 : /msg [id], /kick [id], /all, /list");
p("━━━━━━━━━━━━━━━━━━━━━━━━━━");
th = new Thread(this);
th.start();
while(true)
{
// 소켓을 계속 생성
s = ss.accept();
//p("소켓생성 완료 : " + s);
SocketAddress addr_client = s.getRemoteSocketAddress();
p("클라이언트의 IP : " + addr_client); // 소켓찍으면 길기때문에 따로 IP만 찍는다.
cm = new OneClientManager(this, s);
cm.start();
}
}catch (IOException ie)
{
p("클라이언트와의 접속 불량");
}finally
{
try
{
s.close();
ss.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
public void run()
{
br_in = new BufferedReader(new InputStreamReader(System.in));
msg_server = "";
try
{
while ((msg_server = br_in.readLine()) != null)
{
if (msg_server.startsWith("/msg"))
{
msg_send();
}
else if (msg_server.startsWith("/kick"))
{
kick_user();
}
else if (msg_server.equalsIgnoreCase("/all"))
{
System.out.print("모두에게 하고 싶은 말 : ");
String msg_all = br_in.readLine();
cm.writeAll("★★★Server★★★ : " + msg_all);
p("Client에게 전달 : " + msg_all);
}
else if (msg_server.equalsIgnoreCase("/list"))
{
list_all();
}
else
{
p(msg_server);
p("명령어 안내 : /msg [id], /kick [id], /all, /list");
}
}
}
catch (IOException e)
{
p("입력중 에러");
}
}
public void msg_send() throws IOException
{
String msg_id = msg_server.substring(5);
Enumeration enums = OneClientManager.v.elements(); //벡터안에 있는 객체들을 한줄로 세운다.
while (enums.hasMoreElements())
{
try
{
cm = (OneClientManager) enums.nextElement();
if (cm.id.equalsIgnoreCase(msg_id))
{
System.out.print(msg_id + "에게 전할말 : ");
String msg_user = br_in.readLine();
cm.dos.writeUTF("★★★Server★★★ : " + msg_user);
}
}
catch (IOException e)
{
p("메시지 전달하지 못함");
}
}
}
public void kick_user() throws IOException
{
String msg_id = msg_server.substring(6);
Enumeration enums = OneClientManager.v.elements(); //벡터안에 있는 객체들을 한줄로 세운다.
while (enums.hasMoreElements())
{
try
{
cm = (OneClientManager) enums.nextElement();
if (cm.id.equalsIgnoreCase(msg_id))
{
System.out.print(msg_id + "에게 마지막으로 전할말 : ");
String msg_user = br_in.readLine();
cm.dos.writeUTF("★★★Server★★★ : " + msg_user);
cm.s.close();
}
}
catch (IOException e)
{
p("메시지 전달하지 못함");
}
}
}
public void list_all()
{
Enumeration enums = OneClientManager.v2.elements();
int n = 0;
while (enums.hasMoreElements())
{
n++;
String user_id = (String) enums.nextElement();
p(n + "번째 유저 : " + user_id);
}
p("이상 총" + n +"명의 유저가 대화방에 있습니다.");
}
public void p(String str)
{
System.out.println(str);
}
public static void main(String[] args)
{
new OnetoMulServer();
}
}
/*
* 1. ClientThread의 이름 : 하나의 클라이언트에 대한 서버측 관리 클래스
* 2. ClientThread의 기능 : 하나의 소켓(클라이언트)에 대해서 계속 읽어서, 브로드 캐스팅해주는 클래스
*/
class OneClientManager extends Thread
{
Socket s;
InputStream is;
OutputStream os;
DataInputStream dis;
DataOutputStream dos;
OnetoMulServer server;
OneClientManager cm;
String id;
int n;
static Vector v = new Vector();
static Vector v2 = new Vector();
public OneClientManager(){}
public OneClientManager(OnetoMulServer server, Socket s)
{
this.s = s;
this.server = server;
v.addElement(this); // 하나의 클라이언트 관리 클래스를 Vector에 넣어준다.
}
public void run()
{
try
{
is = s.getInputStream();
dis = new DataInputStream(is);
os = s.getOutputStream();
dos = new DataOutputStream(os);
id = dis.readUTF();
dos.writeUTF("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
dos.writeUTF(" 안녕하세요 RnB.Wan의 채팅 서버입니다.");
dos.writeUTF(" 네티켓을 지켜주시기 바랍니다.");
dos.writeUTF("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
p(id + "님이 접속하셨습니다.");
writeAll(id + "님이 접속하셨습니다.");
v2.addElement(id);
n = v.size();
p(n + "명이 현재 대화에 참여하고 있습니다.");
p("━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ");
writeAll(n + "명이 현재 대화에 참여하고 있습니다.");
writeAll("━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ");
String msg_client = "";
while (true)
{
msg_client = dis.readUTF();
p(id + "의 말 : " + msg_client);
writeAll(id + "의 말 : " + msg_client);
}
}
catch (IOException e)
{
v2.removeElement(id);
v.removeElement(this);
p(id + "님과 연결 끊김");
writeAll("━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ");
writeAll(id + "님이 나가셨습니다.");
n = v.size();
writeAll(n + "명이 현재 대화에 참여하고 있습니다.");
writeAll("━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ");
if (n == 0)
{
try
{
p("3초뒤 서버를 셧다운합니다.");
Thread.sleep(3000);
System.exit(1);
}
catch (InterruptedException e1)
{
p("예외발생 : " + e1);
}
}
}
}
public void writeAll(String msg_client)
{
String msg = msg_client;
Enumeration enums = v.elements(); //벡터안에 있는 객체들을 한줄로 세운다.
while (enums.hasMoreElements())
{
try
{
cm = (OneClientManager) enums.nextElement();
cm.dos.writeUTF(msg);
cm.dos.flush();
}
catch (IOException e)
{
p("메시지 전달하지 못함");
}
}
}
public void p(String str)
{
System.out.println(str);
}
}
클라이언트 프로그램
package com.hkp.socket;
import java.io.*;
import java.net.*;
public class OnetoMulClient extends Thread
{
Socket s;
InputStream is;
OutputStream os;
DataInputStream dis;
BufferedReader br_in;
DataOutputStream dos;
Thread th;
String ip, port, id;
public OnetoMulClient()
{
try
{
br_in = new BufferedReader(new InputStreamReader(System.in));
System.out.print("접속하려는 서버의 IP : ");
ip = br_in.readLine();
if (ip.equalsIgnoreCase(""))
{
ip = "127.0.0.1";
p("Localhost로 연결합니다.");
}
System.out.print("서버의 포트 번호 : ");
port = br_in.readLine();
if (port.equalsIgnoreCase(""))
{
port = "8888";
p("8888포트로 연결합니다.");
}
System.out.print("접속하려는 ID : ");
id = br_in.readLine();
if (id.length() == 0 | id.equalsIgnoreCase("server"))
{
while (id.length() == 0 | id.equalsIgnoreCase("server"))
{
p("틀린 아이디 입니다. 제대로 된 아이디를 입력하세요");
System.out.print("접속하려는 ID : ");
id = br_in.readLine();
}
}
s = new Socket(ip, Integer.parseInt(port));
p("서버에 접속 되었습니다.");
os = s.getOutputStream();
dos = new DataOutputStream(os);
dos.writeUTF(id);
th = new Thread(this);
th.start();
String msg = "";
while((msg = br_in.readLine()) != null)
{
dos.writeUTF(msg);
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
public void run()
{
try
{
is = s.getInputStream();
dis = new DataInputStream(is);
String msg_server = "";
while((msg_server = dis.readUTF()) != null)
{
p(msg_server);
}
}
catch (IOException e)
{
p("서버 다운 or 강퇴입니다.");
p("3초후 클라이언트를 닫습니다.");
try
{
Thread.sleep(3000);
System.exit(1);
}
catch (InterruptedException e1)
{
p("예외 발생");
}
}
}
public static void main(String[] args)
{
new OnetoMulClient();
}
public void p(String str)
{
System.out.println(str);
}
}
package com.hkp.socket;
import java.io.*;
import java.net.*;
public class UDPTotal extends Thread
{
DatagramSocket ds_s;
DatagramPacket dp_s;
DatagramSocket ds_c;
DatagramPacket dp_c;
InetAddress ia;
BufferedReader br;
Thread th;
static String ip;
public UDPTotal()
{
try
{
ds_s = new DatagramSocket(10000);
p("받을 편지함 대기중.....");
th = new Thread(this);
th.start();
while(true)
{
byte[] b = new byte[100];
dp_s = new DatagramPacket(b, 0, b.length);
ds_s.receive(dp_s);
byte data[] = dp_s.getData();
String msg_client = new String(data).trim();
// trim() --> 바이트에서 빈공간들을 잘라내서 버려버린다.
InetAddress ia_client = dp_s.getAddress();
String ip_client = ia_client.getHostAddress();
p("MSG from [" + ip_client + "] : " + msg_client);
}
}
catch (SocketException e)
{
p("10000번 포트는 사용 중 : " + e);
}
catch (IOException e1)
{
p("클라이언트의 메시지 받다가 에러 : " + e1);
}finally
{
ds_s.close();
}
}
public void run()
{
try
{
ds_c = new DatagramSocket();
br = new BufferedReader(new InputStreamReader(System.in));
p("보낼 메시지 입력하라!");
ia = InetAddress.getByName(ip);
String msg_client = "";
while ((msg_client = br.readLine()) != null)
{
byte[] b = msg_client.getBytes();
dp_c = new DatagramPacket(b, 0, b.length, ia,10000);
ds_c.send(dp_c);
p("보낼 메시지 입력하라!");
}
}
catch (SocketException e)
{
p("사용중인 포트 사용 시도 예외 : " + e);
}
catch (IOException e1)
{
p("메시지 입력중 예외 : " + e1);
}finally
{
try
{
br.close();
ds_c.close();
}
catch (IOException e2)
{
e2.printStackTrace();
}
}
}
public static void main(String[] args)
{
if (args.length != 1)
{
System.out.println("사용법 : java.exe UDPTotal [IP넘버]");
return;
}
ip = args[0];
new UDPTotal();
}
public void p(String str)
{
System.out.println(str);
}
}
'Dev. 자바 > API 및 이론' 카테고리의 다른 글
[Java] 자바8 알아보기 (0) | 2014.08.18 |
---|---|
[JAVA 팁] 성능개선을 위한 String 관련 사용 팁 (0) | 2014.02.10 |
[JAVA] 쓰레드(Thread)의 기초 및 이론, 활용, 응용, 예제 (2) | 2013.01.23 |
내부클래스 (0) | 2013.01.22 |
자바 예외(Exception)의 계층구조 및 자주 보이는 예외 설명 (0) | 2012.09.17 |