2020.11.18 일지
오늘의 요약
오늘 배운 것은 1:1 파일주고받는 채팅 만들기이다.
FServer.java
import java.io.*;
import java.net.*;
class FServer {
String fname = "CHEEZE(치즈) _ Love You(좋아해)(bye).mp4";
int port = 4000;
ServerSocket ss;
Socket s;
InputStream is; //Node
BufferedInputStream bis; //Filter
FileOutputStream fos; //Node
BufferedOutputStream bos; //Filter
FServer(){
try{
ss = new ServerSocket(port);
pln("파일 서버가 "+port+"번 포트에서 대기중..");
s = ss.accept();
is = s.getInputStream(); // 인풋스트림으로 뽑아내야겠지?
bis = new BufferedInputStream(is, 4096);
// 일반적으로 바이트 코드를 사용할 땐 인풋스트림을 사용하는게 좋음
// 쇼핑카트는 버퍼드인풋스트림으로 생각하면 됨
fos = new FileOutputStream(fname);
bos = new BufferedOutputStream(fos, 4096);
// 쇼핑카트 사이즈는 동일하게 해주는 것이 좋다
receive();
}catch(IOException ie){
}
}
void receive(){ // 파일 받는 메소드 socket -> file
byte bs[] = new byte[1024];
int i=0;
long total = 0L;
try{
while((i=bis.read(bs)) != -1){ // 파일을 다 읽으면 -1을 리턴하기 때문에 -1이 아닐떄
bos.write(bs, 0, i); // 0번부터 i번째 까지 써라
pln("받는 중..."+ ( total+=i ) + "bytes");
}
bos.flush(); // i는 byte갯수를 리턴함, 끝까지 가면 -1을 반환한다 그래서 -1이 아니면 까지 조건을 걸어둠
pln("파일("+fname+": "+total+"bytes) 받기 완료!!");
}catch(IOException ie){
}finally{
closeAll();
}
}
void closeAll(){
try{
bis.close();
bos.close();
is.close();
fos.close();
s.close();
ss.close();
}catch(IOException ie){}
}
void pln(String str){
System.out.println(str);
}
public static void main(String[] args) {
new FServer();
}
}
FClient.java
import java.io.*;
import java.net.*;
class FClient {
Socket s;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
FileInputStream fis; //Node
OutputStream os; //Node
BufferedInputStream bis; //Filter
BufferedOutputStream bos; //Filter
String fname = "C://Users//bit//Desktop//CHEEZE(치즈) _ Love You(좋아해)(bye).mp4";
FClient(){
connect();
}
void connect(){ //서버와 접속
try{
p("서버IP(기본:127.0.0.1): ");
String ip = br.readLine();
if(ip != null) ip = ip.trim();
if(ip.length() == 0) ip = "127.0.0.1";
p("PORT(기본:4000): ");
String portStr = br.readLine();
if(portStr != null) portStr = portStr.trim();
if(portStr.length() == 0) portStr = "4000";
int port = Integer.parseInt(portStr);
if(port<0 || port>65535){
pln("범위가 유효하지 않은 포트임");
connect();
return;
}
s = new Socket(ip, port);
ready();
}catch(IOException ie){}
}
void ready(){ // 위에서 만든 객체를 채워 넣어야겠지?
try{
fis = new FileInputStream(fname);
bis = new BufferedInputStream(fis, 4096);
os = s.getOutputStream();
bos = new BufferedOutputStream(os, 4096);
send();
}catch(FileNotFoundException fe){
}catch(IOException ie){}
}
void send(){ //file -> socket
byte bs[] = new byte[1024]; // 계란판의 사이즈를 키울 경우, bs라는 객체를 만들때 메모리가 커지는 거임, 다만 반복문 돌아가는 횟수가 줄어듬
int i=0;
long total = 0L;
try{
while((i=bis.read(bs)) != -1){
bos.write(bs, 0, i);
pln("전송 중..."+ ( total+=i ) + "bytes"); // 프린팅 하는 건 비효율적이다, 그래서 좀 느려질 수 있음 UI로 바꿔주던가 주석처리 해줘야함
}
bos.flush(); // i는 byte갯수를 리턴함, 끝까지 가면 -1을 반환한다 그래서 -1이 아니면 까지 조건을 걸어둠
pln("파일("+fname+": "+total+"bytes) 전송 완료!!");
}catch(IOException ie){
}finally{
closeAll();
}
}
void closeAll(){
try{
bis.close();
bos.close();
fis.close();
os.close();
s.close();
}catch(IOException ie){}
}
void pln(String str){
System.out.println(str);
}
void p(String str){
System.out.print(str);
}
public static void main(String[] args) {
new FClient();
}
}
UServer.java
import java.net.*;
import java.io.*;
class UServer {
DatagramSocket ds; // 메세지함(우체통), 애플리케이션에서 주고 받을 데이터와 관련된 클래스
DatagramPacket dp; // 메세지틀(편지봉투), 실제 데이터의 전송을 책임지는 클래스
int port = 5000; // 포트 번호 정수형태로 받음
UServer(){ // UServer 생성자 호출
try{ // UServer 생성자의 예외 발생 구문
ds = new DatagramSocket(port); // DatagramSocket에 port를 담아 호출해준다.
pln(port + "번에서 UDP서버 대기중.."); // 포트 몇번에서 대기중이라고 모니터에 출력
byte buf[] = new byte[2048]; // 버퍼를 잡아준다.
dp = new DatagramPacket(buf, buf.length); // 편지봉투에 버퍼와, 버퍼의 길이를 담아 호출해준다.
while(true){ // 무한루프 시작, 계속해서 통신할 수 있도록!
ds.receive(dp); // api 찾아보니 이 소켓에서 데이터 그램 패킷을 받는다,
// 이 메서드가 반환되면 DatagramPacket의 버퍼가 수신 된 데이터로 채워진다!
// 데이터 그램 패킷에는 보낸 사람의 IP 주소와 보낸 사람 컴퓨터의 포트 번호도 포함됨!
String msg = new String(buf); // 입력 받는 메세지를 새로운 스트링에 buf로 담고
msg = msg.trim(); // 받은 메세지의 공백을 제거해줌
pln("Client>>> " + msg); // client>>>의 msg를 모니터에 출력
for(int i=0; i<buf.length; i++) buf[i]=0; // buf가 한 번 담겨진 배열을 한번 더 쓰기때문에 "가, 나나, 다" 쓰면 "가,나나,다나" 이런식으로 출력됨
// 이럴때 배열을 새로 만들어주거나 배열을 초기화 해줘야 함 어떻게? 이런 반복문을 통해서 초기화 해줌
}
}catch(SocketException se){
}catch(IOException ie){
}finally{
ds.close(); // 마침내 DatagramSocket 을 닫아줌
}
}
void pln(String str){
System.out.println(str);
}
public static void main(String args[]){
new UServer();
}
}
UClient.java
import java.net.*;
import java.io.*;
class UClient {
DatagramSocket ds; // 메세지함(우체통)
DatagramPacket dp; // 메세지틀(편지봉투)
int port = 5000; // 포트번호 5000을 적어줌
String ip;
String ipHeader = "192.168.0."; // ip full주소 말고 끝자리만 받으려고 적어주는 변수
BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); // 입력 받으려고 node, bridge, filter 모두 한꺼번에 선언해준 것
void init(){
inputIp();
try{
ds = new DatagramSocket(); // ip가 셋팅이 됐음 데이터 소켓 만들어줌 (UClient 내 try캐치문)
while(true){ // 무한루프를 돌리는데, 돌리는 이유는 원래 한 번 전송하고 나면 끝인데 계속 전송하게끔 하려고 무한루프 시작!
p("전달할 메세지: ");
String msg = br.readLine(); // 사용자 입력값 받고
if(msg != null) msg = msg.trim(); // 공백제거
byte[] buf = msg.getBytes(); // byte타입의 buf라는 배열에 메세지의 바이트를 얻음
InetAddress ia = InetAddress.getByName(ip); // InetAddress 클래스는 IP 주소를 표현한 클래스므로, 서버의 ip 주소를 나타냄
// 자바에서는 모든 IP 주소를 InetAddress 클래스를 사용함
dp = new DatagramPacket(buf, buf.length, ia, port);
// datagrampacket API를 찾으면 여러가지 파라미터를 넣을 수 있는 것들이 있는데, 오버로딩 개념에 의해 이걸 선택함
// buf, buf의 길이, 아이피 객체를 담은 아이피, 포트번호 이렇게 담는다.
ds.send(dp); // 그 다음에 ds의 메소드를 send라는 메소드를 사용하여 dp를 보내준다.
pln("전송 완료!!");
}
}catch(SocketException se){
init();
}catch(UnknownHostException ue){
pln("네트웍상에 해당서버("+ip+")를 찾을 수 없음");
init(); //
}catch(IOException ie){
init();
}finally{
ds.close();
}
}
void inputIp(){ // ip 끝자리만 받는 부분
try{
p("IP(끝자리): ");
String ipTail = br.readLine();
if(ipTail != null) ipTail = ipTail.trim(); // tail도 실수로 공백이 들어갈 수 있으므로 공백처리
if(ipTail.length() != 0){ // 그냥 엔터를 칠 수도 있으므로, length = 0 이 아닐때만 ip를 생성해라
ip = ipHeader + ipTail;
}else{
inputIp(); // length = 0 이면 한 번 더 입력받게끔 함
}
}catch(IOException ie){
inputIp();
}
}
void pln(String str){
System.out.println(str);
}
void p(String str){
System.out.print(str);
}
public static void main(String[] args)
{
new UClient().init();
}
}
알게된 개념
TCP | UDP |
---|---|
전화 | 쪽지 |
연결지향 | 비연결지향 |
일단 네트워크가 연결되면 연결이 종료될때까지 유지 | 데이터의 전송이 끝나면 연결을 끊음 |
데이터의 소실 확률 없음 | 데이터의 소실 확률 있음 |
속도가 느림 | 속도가 빠름 |
Author And Source
이 문제에 관하여(2020.11.18 일지), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@peachy/study-023저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)