반응형
시간 정보 전송
package kr.or.ddit.udp;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class UdpSender {
private DatagramSocket ds;
private DatagramPacket dp;
private byte[] msg; // 데이터 송수신을 위한 바이트배열
public UdpSender(int port) {
try {
// 메시지 수신을 위한 포트번호 설정
ds = new DatagramSocket(8888);
} catch (SocketException e) {
e.printStackTrace();
}
}
public void start() {
while(true) {
// 데이터를 수신하기 위한 패킷을 생성한다.
msg = new byte[1];
dp = new DatagramPacket(msg, 1);
System.out.println("패킷 수신 대기 중...");
try {
ds.receive(dp);
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("패킷 수신 완료...");
// 수신한 패킷으로부터 송신자의 IP주소 및 포트번호 가져온다.
InetAddress addr = dp.getAddress();
int port = dp.getPort();
// 현재 시간을 시분초 형태([hh:mm:ss])로 전송한다.
SimpleDateFormat sdf = new SimpleDateFormat("[hh:mm:ss]");
String time = sdf.format(new Date());
msg = time.getBytes(); // 시간 데이터를 바이트 배열로 변환
// 패킷을 생성해서 송신자에게 전송한다.
dp = new DatagramPacket(msg, msg.length, addr, port);
try {
ds.send(dp);
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("현재 시간 전송 완료...");
}
}
public static void main(String[] args) {
new UdpSender(8888).start();
}
}
package kr.or.ddit.udp;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
public class UdpReceiver {
private DatagramSocket ds;
private DatagramPacket dp;
private byte[] msg;
public UdpReceiver() {
msg = new byte[100];
try {
// 포트번호를 명시하지 않으면, 이용가능한 임의의 포트번호로 할당됨.
ds = new DatagramSocket();
} catch (SocketException e) {
e.printStackTrace();
}
}
public void start() throws IOException {
// IP 변경 필요
InetAddress addr = InetAddress.getByName("192.168.144.//");
dp = new DatagramPacket(msg, 1, addr, 8888);
ds.send(dp);
////////////////////////////////////
dp = new DatagramPacket(msg, msg.length);
ds.receive(dp);
System.out.println("수신한 현재 시간 정보 => " + new String(dp.getData()));
ds.close(); // 소켓 종료
}
public static void main(String[] args) throws Exception {
new UdpReceiver().start();
}
}
파일 전송
package kr.or.ddit.udp;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
public class UdpFileSender {
private DatagramSocket ds;
private DatagramPacket dp;
private InetAddress receiveAddr;
private int port;
private File file;
public UdpFileSender(String receiveIp, int port) {
try {
receiveAddr = InetAddress.getByName(receiveIp);
} catch (UnknownHostException e) {
e.printStackTrace();
}
this.port = port;
try {
ds = new DatagramSocket();
} catch (SocketException e) {
e.printStackTrace();
}
file = new File("D:/D_Other/Tulips.jpg");
if(!file.exists()) {
System.out.println("해당 파일이 존재하지 않습니다.");
System.exit(0);
}
}
public void start() {
long fileSize = file.length();
long totalReadBytes = 0;
long startTime = System.currentTimeMillis();
try {
sendData("start".getBytes()); // 전송 시작을 알려주기 위한 문자열 전송...
sendData(file.getName().getBytes()); // 파일명 전송
sendData(String.valueOf(fileSize).getBytes()); // 총 파일 크기 전송
////////////////////////////////////////////////////
FileInputStream fis = new FileInputStream(file);
byte[] buffer = new byte[1000];
while(true) {
try {
// 패킷 전송 간의 시간 간격을 주기 위해서
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
int readBytes = fis.read(buffer, 0, buffer.length);
if(readBytes == -1) { // 다 읽은 경우
break;
}
sendData(buffer, readBytes); // 읽어온 파일 데이터 전송하기
totalReadBytes += readBytes;
System.out.println("진행 상태 : " + totalReadBytes + "/" + fileSize
+ " Byte(s) (" + (totalReadBytes * 100 / fileSize) + "%)");
}
long endTime = System.currentTimeMillis();
long diffTime = endTime - startTime;
double transferSpeed = fileSize / diffTime;
System.out.println("걸린 시간 : " + diffTime + " (ms)");
System.out.println("평균 전송 속도 : " + transferSpeed + " (Bytes/ms)");
System.out.println("전송 완료...");
fis.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
/**
* 바이트배열 전송하기 위한 메서드
* @param buffer 전송할 데이터
* @param readBytes 실제 데이터 사이즈
*/
private void sendData(byte[] buffer, int readBytes) {
try {
dp = new DatagramPacket(buffer, readBytes, receiveAddr, port);
ds.send(dp);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 바이트배열 전송하기 위한 메서드
* @param buffer 전송할 데이터
*/
private void sendData(byte[] buffer) {
sendData(buffer, buffer.length);
}
public static void main(String[] args) {
// IP 주소 변경 필요
new UdpFileSender("localhost", 8888).start();
}
}
package kr.or.ddit.udp;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
public class UdpFileReceiver {
private DatagramSocket ds;
private DatagramPacket dp;
private byte[] buffer;
public UdpFileReceiver(int port) {
try {
ds = new DatagramSocket(port);
} catch (SocketException e) {
e.printStackTrace();
}
}
public void start() throws IOException {
long fileSize = 0;
long totalReadBytes = 0;
int readBytes = 0;
System.out.println("파일 수신 대기 중...");
String str = new String(receiveData()).trim();
if(str.equals("start")) {
// 전송 파일명 받기
str = new String(receiveData()).trim();
FileOutputStream fos = new FileOutputStream("d:/D_Other/" + str);
// 전송 파일크기 받기
str = new String(receiveData()).trim();
fileSize = Long.parseLong(str);
long startTime =System.currentTimeMillis();
// 파일 내용 수신 시작...
while(true) {
byte[] data = receiveData();
readBytes = dp.getLength(); // 받은 데이터 크기
fos.write(data, 0, readBytes);
totalReadBytes += readBytes;
System.out.println("진행 상태 : " + totalReadBytes + "/" + fileSize
+ " Byte(s) (" + (totalReadBytes * 100 / fileSize) + "%)");
if(totalReadBytes >= fileSize) {
break;
}
}
long endTime = System.currentTimeMillis();
long diffTime = endTime - startTime;
double transferSpeed = fileSize / diffTime;
System.out.println("걸린 시간 : " + diffTime + " (ms)");
System.out.println("평균 수신 속도 : " + transferSpeed + " (Bytes/ms)");
System.out.println("수신 완료...");
fos.close();
ds.close();
}
}
/**
* 데이터 수신하기
* @return 수신한 바이트배열 데이터
*/
private byte[] receiveData() {
buffer = new byte[1000]; // 버퍼 초기화
dp = new DatagramPacket(buffer, buffer.length);
try {
ds.receive(dp);
} catch (IOException e) {
e.printStackTrace();
}
return dp.getData(); // 데이터를 가져옴
}
public static void main(String[] args) throws IOException {
new UdpFileReceiver(8888).start();
}
}
HTTP 방식의 통신
- 메시지 구조
- 프로토콜 특징
1. 요청을 하면 그에 대한 응답을 보냄
2. 클라이언트 상태를 보존하지 않음(무상태 프로토콜)
3. 연결을 유지 하지 않음(비 연결성)
package kr.or.ddit.http;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.URLConnection;
import java.net.URLDecoder;
import java.util.StringTokenizer;
/**
* 간단한 웹서버 예제
* @author PC-10
*
*/
public class MyHttpServer {
private final int port = 80;
private final String encoding = "UTF-8";
public void start() {
ServerSocket server = null;
try {
System.out.println("HTTP 서버가 시작되었습니다...");
server = new ServerSocket(80);
while(true) {
Socket socket = server.accept();
// Http 핸들러 호출 및 시작(스레드)
HttpHandler handler = new HttpHandler(socket);
handler.start();
}
} catch (IOException ex) {
ex.printStackTrace();
} finally {
try {
server.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* HTTP 요청 처리를 위한 핸들러 스레드
* @author PC-10
*
*/
class HttpHandler extends Thread {
private final Socket socket;
public HttpHandler(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
BufferedOutputStream bos = null;
BufferedReader br = null;
try {
bos = new BufferedOutputStream(socket.getOutputStream());
br = new BufferedReader(
new InputStreamReader(socket.getInputStream()) );
// Request Line
String reqLine = br.readLine(); // 첫줄은 요청라인...
// System.out.println("Request Line : " + reqLine);
// 요청헤더 정보 파싱하기
StringBuilder sb = new StringBuilder();
while(true) {
String str = br.readLine();
if(str.equals("")) { // Empty Line인 경우...
break;
}
sb.append(str + "\n");
}
// 헤더 정보
String reqHeaderStr = sb.toString();
// System.out.println("요청헤더 정보 : " + reqHeaderStr);
String reqPath = ""; // 요청경로
// 요청 페이지 정보 가져오기
StringTokenizer st = new StringTokenizer(reqLine);
while(st.hasMoreTokens()) {
String token = st.nextToken();
if(token.startsWith("/")) {
reqPath = token;
}
}
///////////////////////////////////////////////////////////
// URL 디코딩 처리하기(한글깨짐 문제 해결하기 위해)
reqPath = URLDecoder.decode(reqPath, encoding);
String filePath = "./WebContent" + reqPath;
System.out.println("filePath : " + filePath);
// 해당 파일이름을 이용하여 Content-Type 정보 추출하기
String ContentType = URLConnection.getFileNameMap()
.getContentTypeFor(filePath);
// css파일인 경우 인식이 잘 안 되서 추가함...
if(ContentType == null && filePath.endsWith(".css")) {
ContentType = "text/css";
}
System.out.println("ContentType: " + ContentType);
File file = new File(filePath);
if(!file.exists()) {
// 에러페이지 생성
makeErrorPage(bos, 404, "Not Found");
return;
}
byte[] body = makeResponseBody(filePath);
byte[] header =
makeResponseHeader(body.length, ContentType);
///////////////////////////////////////////////////////////
bos.write(header); // 헤더 전송
// 응답 내용 보내기 전에 반드시 Empty Line 보내야 한다.
bos.write("\r\n\r\n".getBytes());
bos.write(body); // 응답 내용 전송
bos.flush(); // 강제 방출...
} catch (IOException ex) {
ex.printStackTrace();
} finally {
try {
socket.close(); // 소켓닫기(연결 끊기)
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 에러 페이지 출력
* @param out 에러페이지 전송할 스트림객체
* @param statusCode 에러코드
* @param statusMsg 에러메시지
*/
private void makeErrorPage(OutputStream out, int statusCode, String statusMsg) {
String statusLin = "HTTP/1.1" + " " + statusCode + " " + statusMsg;
try {
out.write(statusLin.getBytes());
out.flush();
} catch (IOException ex) {
ex.printStackTrace();
}
}
/**
* 응답헤더 생성하기
* @param length 응답내용 크기
* @param contentType 마임타입
* @return 응답헤더 바이트배열
*/
private byte[] makeResponseHeader(int length, String contentType) {
String header = "HTTP/1.1 200 OK\r\n" // status line
+ "Server: MyHttpServer 1.0\r\n"
+ "Content-length: " + length + "\r\n"
+ "Content-Type: " + contentType + "; charset=UTF-8";
return header.getBytes();
}
/**
* 응답내용 생성하기
* @param filePath 응답으로 사용할 파일경로
* @return 응답내용 바이트 배열
*/
private byte[] makeResponseBody(String filePath) {
FileInputStream fis = null;
byte[] data = null;
try {
File file = new File(filePath);
data = new byte[(int) file.length()];
fis = new FileInputStream(filePath);
fis.read(data);
} catch (IOException ex) {
ex.printStackTrace();
} finally {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return data;
}
}
public static void main(String[] args) {
new MyHttpServer().start();
}
}
=> 작동 후 그 사람의 IP로 웹페이지의 URL에 입력시 그 html과 관련된 화면이 보인다.
반응형
'자바' 카테고리의 다른 글
[Java 고급] 27장 쿠키 (0) | 2024.02.21 |
---|---|
[Java 고급] 26장 서블릿 및 설정 (0) | 2024.02.19 |
[Java 고급] 24장 TCP 방식의 통신 (0) | 2024.02.16 |
[Java 고급] 23장 소켓 (1) | 2024.02.15 |
[Java 고급] 22장 IP주소 정보 (0) | 2024.02.14 |