MyServer.java
작성public class MyServer {
//bad code close 철저히
public static void main(String[] args) throws Exception{
//ServerSocket은 손님을 기다리는 역할
ServerSocket serverSocket = new ServerSocket(9999);
System.out.println("Ready...");
while (true) {
//손님이 오면 accept => socket 생성 = client와 연결된 연락책?
Socket client = serverSocket.accept();
System.out.println(client);
OutputStream out = client.getOutputStream();
File file = new File("C:\\zzz\\aaa.jpg");
//아래 4줄이 있어서 웹구현 가능해지는 것
//HTTP 헤더
out.write(new String("HTTP/1.1 200 OK\r\n").getBytes());
out.write(new String("Cache-Control: private\r\n").getBytes());
out.write(new String("Content-Length: "+file.length()+"\r\n").getBytes());
out.write(new String("Content-Type: image/jpeg\r\n\r\n").getBytes());
//out.write(97);
InputStream fin = new FileInputStream("C:\\zzz\\aaa.jpg");
byte[] buffer = new byte[1024*8]; //data 담을 계란판 buffer
while (true) {
int count = fin.read(buffer); //몇 개나 새로운 data 읽었는지
if (count == -1) { break; } //새로운 data없으면 -1 => break
out.write(buffer, 0, count); //buffer의 내용물을 맨 앞부터 새로 읽은 개수만큼만 write
}//end while
//fin.close();
out.close();
client.close();
//연결여부만 확인하고 바로 종료
}//end while
}
}
MyClient.java
작성public class MyClient {
//bad code
public static void main(String[] args) throws Exception {
Socket socket = new Socket("192.168.0.0", 9999);
System.out.println(socket);
InputStream in = socket.getInputStream();
FileOutputStream fos = new FileOutputStream("C:\\zzz\\get.jpg");
byte[] buffer = new byte[1024*8]; //data 담을 바가지
while (true) {
int count = in.read(buffer); //몇 개나 새로운 data 읽었는지
if (count == -1) { break; } //새로운 data없으면 -1 => break
fos.write(buffer, 0, count); //buffer의 내용물을 맨 앞부터 새로 읽은 개수만큼만 write
}//end while
fos.close();
socket.close();
}
}
받는 파일이 뭔지 모름
원하는 파일만 받을 수 XX 보내주는 파일만 받을 수 있음
파일이름 + 파일 데이터 따로 => 프로토콜 = 약속
웹에서 프로토콜 => HTTP.
해당 프로토콜에 맞게해야 주고받기 가능
MyServer 먼저 실행 후 Ready확인하고 MyClient 실행
Server :
Ready...
Client :
Socket[addr=/192.168.0.0,port=9999,localport=6774]
Server :
Ready...
Socket[addr=/192.168.0.0,port=6774,localport=9999]
Server는 while loop로 계속 돌고있기때문에 빨간네모 Stop 눌러서 종료시켜줘야함
아직 데이터를 다 보내지 못한 상황에서 close하면 연결 끊기는 문제
fin -> out -> client였을때 문제 발생함
close는 꼭 해줘야하지만 그 타이밍도 중요하다 너무 빨리해도 문제 안해도 문제인것
현재 방식은 한번 접속하고 종료되고 한번 접속하고 종료되고 형식
=> 나중에 while과 multi-thread 를 이용해 해결 가능
순서 / 구조 결정되어있음
클라이언트가 보내고 = Request
서버가 응답 = Response
HTTP -> stateless 무상태
처음부터 끝까지 연결된상태에서 => stateful = 연결지속형
ex.게임서버
OneToOneServer.java
작성public class OneToOneServer {
//bad code
public static void main(String[] args) throws Exception {
Scanner keyScanner = new Scanner(System.in);
ServerSocket serverSocket = new ServerSocket(9999);
System.out.println("Ready...");
//서버는 먼저 읽고 클라이언트는 계속 보냄
//클라이언트가 보내는 메세지 읽으려면 몇바이튼지 알아야되는데 모름
// => 알기위해 Scanner사용
//Scanner는 엔터(\n) 전까지 읽어들임
Socket client = serverSocket.accept();
System.out.println("Client connected...");
//대부분의 경우 client가 먼저 전송함
// = 서버는 읽어오기 먼저
InputStream in = client.getInputStream();
OutputStream out = client.getOutputStream();
Scanner inScanner = new Scanner(in); //InputStream과 연결된 scanner
for (int i = 0; i < 100; i++) {
String line = inScanner.nextLine();
//뭘 원하는지 읽기
System.out.println(line);
String myMsg = keyScanner.nextLine()+"\n";
out.write(myMsg.getBytes());
}
//다 썼으면 close 닫아주기
inScanner.close();
in.close();
client.close();
serverSocket.close();
}
}
OneToOneClient.java
작성public class OneToOneClient {
//bad code
public static void main(String[] args) throws Exception {
Scanner keyScanner = new Scanner(System.in);
Socket socket = new Socket("192.168.0.0", 9999);
System.out.println("Connected...");
//server로 보내야하니까 OutputStream
OutputStream out = socket.getOutputStream();
InputStream in = socket.getInputStream();
Scanner inScanner= new Scanner(in);
//문자열을 byte[]로 바꿔서 out.write(바이트배열)
//Server 에선 읽을때 scanner 사용
//for loop로 i회수 도는만큼 채팅 가능
for (int i = 0; i < 100; i++) {
String msg = keyScanner.nextLine() + "\n";
//\n을 사용해줘야 server의 scanner가 끊어읽을 수 있음
//안쓰면 인식불가 scanner가 끊을 수 없어서!
out.write(msg.getBytes());
System.out.println("----------------------------------");
System.out.println(inScanner.nextLine());
}
out.close();
socket.close();
}
}
반드시 받아야만 보낼 수 있고 받지않으면 보낼 수 없음, 연속으로 보내는거 불가능
=> 해결 : Thread 사용
현재 상황에선 여럿이서 불가능
한번 연결되면 for끝날때까지 끊을 수 없음
=> 해결 : 사용자가 서로 다이렉트로 말고 서버에 중계자역할 시키면?
연결 안맺고있다가 메세지 보낼때만 잠깐 연결될 수 있음
파일 입출력을 빠르게하는 방법
buffer 존재 1024*8
속도 비교 용량이 큰 파일 복사 속도 비교
EchoServer.java
생성public class EchoServer {
//bad code
public static void main(String[] args) throws Exception {
Map<String, String[]> map = new HashMap<>();
map.put("kor", new String[]{"불고기", "비빔밥"});
map.put("jap", new String[]{"초밥", "라멘"});
map.put("wes", new String[]{"피자", "파스타"});
map.put("chn", new String[]{"짜장면", "짬뽕"});
//서버소켓 준비
ServerSocket serverSocket = new ServerSocket(9999);
System.out.println("Ready....");
//루프 시작
while(true) {
//연결 accept() Socket
Socket socket = serverSocket.accept();
System.out.println(socket.getInputStream());
//클라이언트가 보낸 메시지 읽기
//연결되자마자 보내게 되어있음
InputStream in = socket.getInputStream();
Scanner inScanner = new Scanner(in);
String msg = inScanner.nextLine();
System.out.println(msg); //kor, jap
String[] arr = map.get(msg);
//읽은 메세지를 다시 전송
String sendMsg = null;
if (arr == null) {
sendMsg = "메뉴를 다시 선택하세요.\n";
} else {
int idx = (int) (Math.random() * arr.length);
sendMsg = msg + ": " + arr[idx] + "\n";
}
OutputStream out = socket.getOutputStream();
out.write(sendMsg.getBytes());
out.flush(); //내용물을 한번에 밀어내는 역할
out.close();
inScanner.close();
in.close();
socket.close();
//소켓 연결 종료
}//end while
}
}
EchoClient.java
생성public class EchoClient {
public static void main(String[] args) throws Exception {
Scanner keyScanner = new Scanner(System.in);
while (true) {
System.out.println("Choice Your Menu");
String msg = keyScanner.nextLine();
if (msg.equalsIgnoreCase("exit")) {
System.out.println("\n--End--"); break;
}
//지연연결 - 연결을 계속 미루다가 필요할때만 연결하고 끊기
Socket socket = new Socket("192.168.0.53", 9999);
InputStream in = socket.getInputStream();
Scanner inScanner = new Scanner(in);
OutputStream out = socket.getOutputStream();
String sendMsg = msg +"\n";
out.write(sendMsg.getBytes()); //전송 완료
System.out.println(inScanner.nextLine());
//한번 연결 후에 다 닫고 반복
out.close();
inScanner.close();
in.close();
socket.close();
}//end while
}
}
server에는 client에서 입력한 값이 계속해서 쌓이고
client에는 입력한 값에 해당하는 map arraylist의 메뉴 중 하나가 불러와지게 됨