ネットワーク通信2
7603 ワード
サーバー
サーバは、2つのスロットを受信する責任を負います->サーバソケット:accept(複数のユーザー接続)
conSocket:accept後の新しいオブジェクトの戻り(実際の責任)-->クライアントに関連付けられたソケット
接続者が1人増えるたびにconsocketは増加し続けます.
package ex07.network.fileServer02;
import java.io.IOException;
import java.io.*;
import java.net.*;
//클라이언트가 요청하는 파일을 전송하는 역할의 서버
public class FileServer {
public static void main(String[] args) {
// 1) 접속을 받아주는 역할의 소켓 객체를 생성
try {
ServerSocket serverSocket = new ServerSocket(9000);
System.out.println("파일 클라이언트 접속 대기...");
// 2)VIPS 안내매니저가 담당 직원을 연결시켜줌
// conSocket이 클라이언트와의 통신을 하는 역할을 한다
// conSocket 내부에는 송/수신 스트림이 생성되어 있다 -->이걸통하면 클라이언트와 통신할 수 있음
Socket conSocket = serverSocket.accept();
System.out.println("파일 클라이언트 접속 완료! ");
//3) 통신을 위해 stream 객체를 얻는다
// 3-1) 수신 stream
InputStream in = conSocket.getInputStream();
DataInputStream dIn = new DataInputStream(in);
// 3-2) 송신 stream
OutputStream out = conSocket.getOutputStream();
DataOutputStream dOut = new DataOutputStream(out);
//4) 파일을 수신한다
// 4-1) 파일명을 수신한다
String fileName = dIn.readUTF();
System.out.println("사용자 요청 파일 " + fileName);
// 4-2) 파일을 연결한다
FileInputStream fIn = new FileInputStream(fileName);
// 4-3) 파일 데이터를 송신한다
while(true) {
// int는 4byte지만 실제로는 1byte만 읽어서 채운다
int data = fIn.read();
if(data == -1) { //더이상 읽을 것이 없다
System.out.println("--- 모두 전송했습니다 ---");
break;
}else { //읽었으면 클라이언트한테 전송한다
dOut.write(data);
}
}
fIn.close(); dOut.close(); out.close();
dIn.close(); in.close(); serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
クライアント
package ex07.network.fileServer02;
import java.io.*;
import java.net.*;
import java.util.Scanner;
public class FileClient {
public static void main(String[] args) {
try {
// 1) 서버에 접속할 소켓 객체를 생성(서버IP, Port)
// 객체가 생성되면 서버와의 스트림이 연결된다
Socket clientSocket = new Socket("127.0.0.1", 9000);
// 2) 키보드 입력 객체를 생성
Scanner sc = new Scanner(System.in);
// 3) 송/수신 stream을 얻는다
// 3-1) 수신 stream
InputStream in = clientSocket.getInputStream();
DataInputStream dIn = new DataInputStream(in);
// 3-2) 송신 stream
OutputStream out = clientSocket.getOutputStream();
DataOutputStream dOut = new DataOutputStream(out);
// 4) 서버로부터 다운로드할 파일 명 입력
System.out.print("다운로드 파일명 입력 >> ");
String fileName = sc.nextLine();
// 5) 파일명을 서버로 전송
dOut.writeUTF(fileName);
System.out.println("서버에 파일명을 보냈습니다~");
// 6) 다운로드 파일을 저장할 파일을 연결
String dFileName = "new_" + fileName;
FileOutputStream outFile = new FileOutputStream(dFileName);
// 7) 서버로부터 파일 다운로드
System.out.println("서버로부터 파일을 다운로드 시작합니다!");
while(true) {
int data = dIn.read();
if(data==-1) {
System.out.println("다운로드 완료! ");
break;
}else {
outFile.write(data);
}
}
System.out.println("클라이언트 종료 ");
outFile.close(); dOut.close(); out.close();
dIn.close(); in.close(); clientSocket.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
マルチスレッド
誰かが返事をしなければ、他の人は止まります.
コンセントごとにスレッドが付いています
DB接続やネットワーク接続では例外処理がよく使われます.
内部問題ではなく予測しにくい外部問題
サーバー
package ex07.network.multiThreadServer04;
import java.io.*;
import java.net.*;
/*
[서버]
1) 동기 서버 : 현재 우리가 만드는 서버는
"멀티스레드 동기 에코 서버"
2) 비동기 서버
*/
/*
[멀티스레드 동기 서버]
1) 장점 : 동시에 여러 클라이언트에 대응할 수 있다
2) 단점 : 접속자가 많아지면 스레드가 많아진다
스레드는 "Context Switching"이 많이 발생한다
그러므로 반응속도가 느려진다
(Apache Server의 특징)
*/
public class MultiThreadEchoServer {
final static int PORT = 9000;
public static void main(String[] args) {
try {
// 1) accept()처리를 위한 "서버 소켓 객체"를 생성한다
// 클라이언트가 접속시 연결 처리 후
// 새로운 통신소켓과 연결해주는 역할(담당자 역할 소켓 부여)
ServerSocket serverSocket = new ServerSocket(PORT);
// 2) 클라이언트가 접속 요청을 할 때마다 계속 accept()처리를
// 해야 한다 - main thread의 역할
while (true) {
System.out.println("클라이언트 접속 대기...");
// clientSocket이 클라이언트와 통신하는 소켓
Socket clientSocket = serverSocket.accept();
// 접속 클라이언트당 1개의 스레드를 배치
// 고객과의 송수신은 스레드 니가 알아서 처리해라
EchoThread echoThread = new EchoThread(clientSocket);
echoThread.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
class EchoThread extends Thread {
private Socket socket;
EchoThread(Socket socket) {
this.socket = socket;
}
// JVM에 의해 할당된 스레드는 run()을 실행하게 된다
// run()에서는 클라이언트의 메시지를 수신 -> 표시 -> Echo 전송
// 을 반복한다
@Override
public void run() {
try {
// 1) 어떤 클라이언트가 접속했나?
InetAddress inetAddr = socket.getInetAddress();
System.out.println(inetAddr.getHostAddress() + "로부터 접속했습니다~");
// 2) 송/수신 stream 객체얻기
// 2-1) 송신 stream
OutputStream out = socket.getOutputStream();
OutputStreamWriter outW = new OutputStreamWriter(out);
PrintWriter pw = new PrintWriter(outW);
// 2-2) 수신 stream
InputStream in = socket.getInputStream();
InputStreamReader inR = new InputStreamReader(in);
BufferedReader br = new BufferedReader(inR);
// 3) Echo 기능 수행 : 수신 -> 표시 -> 송신
while(true) {
//3-1) 수신
String line = br.readLine();
if(line==null) {
System.out.println("클라이언트 접속 단절!");
break;
}else { // 정상적으로 메시지가 담겨있다면
//3-2) 화면에 표시
System.out.println(inetAddr.getHostAddress() +
" 클라이언트로부터 수신 : " + line);
//3-3) 클라이언트에 echo 송신
pw.println(line);
pw.flush();
}
}
System.out.println(inetAddr.getHostAddress() +
" 클라이언트 접속 종료!!!");
pw.close(); outW.close(); out.close();
br.close(); inR.close(); in.close();
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
クライアント
package ex07.network.multiThreadServer04;
import java.io.*;
import java.net.*;
import java.util.Scanner;
public class EchoLoopClient {
public static void main(String[] args) throws UnknownHostException, IOException {
Socket clientSocket = new Socket("106.240.16.169", 9000);
InputStreamReader inK = new InputStreamReader(System.in);
BufferedReader keyboard = new BufferedReader(inK);
OutputStream out = clientSocket.getOutputStream();
OutputStreamWriter outW = new OutputStreamWriter(out);
PrintWriter pw = new PrintWriter(outW);
// 수신
InputStream in = clientSocket.getInputStream();
InputStreamReader inR = new InputStreamReader(in);
BufferedReader br = new BufferedReader(inR);
while(true) {
System.out.print("입력 >> ");
String line = keyboard.readLine();
if(line == null) {
System.out.println("서버 종료");
break;
}
else if(line.equals("quit")) {
System.out.println("클라이언트 Quit");
break;
}
System.out.println("서버로 전송 : " + line);
pw.println(line);
pw.flush();
// 서버가 echo하는 것을 받아서 출력
String echo = br.readLine();
System.out.println("서버로부터 수신 : " + echo);
}
// 5) 열려있는 객체들을 모두 닫는다
pw.close();
outW.close();
out.close();
br.close();
inR.close();
in.close();
clientSocket.close();
}
}
Reference
この問題について(ネットワーク通信2), 我々は、より多くの情報をここで見つけました https://velog.io/@jinkyung/네트워크-통신2テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol