이 기사에서는 주로 JAVA에서 네이티브 소켓 통신 메커니즘을 구현하는 원리를 소개합니다. 편집자는 이것이 꽤 좋다고 생각하므로 지금 공유하고 참고용으로 제공하겠습니다. 편집자를 따라가서 살펴보겠습니다. 이 기사에서는 JAVA의 기본 소켓 통신 메커니즘을 소개하고 이를 모든 사람과 공유합니다.
현재 환경
jdk == 1.8
오늘은 JAVA의 소켓 통신 문제입니다. 여기서는 이제 Baidu 사이트와 통신해야 한다고 가정하고 가장 간단한 1요청 1응답 모델을 예로 들어보겠습니다. 이를 달성하기 위해 JAVA의 기본 소켓을 어떻게 사용할 수 있습니까?
먼저 소켓 연결을 설정해야 합니다(핵심 코드)
import java.net.InetSocketAddress; import java.net.Socket; import java.net.SocketAddress; // 初始化 socket Socket socket = new Socket(); // 初始化远程连接地址 SocketAddress remote = new InetSocketAddress(host, port); // 建立连接 socket.connect(remote);
소켓 연결을 성공적으로 설정한 후 입력 출력 스트림을 얻을 수 있으므로 통신의 본질은 입력 및 출력 스트림을 처리하는 것입니다. 입력 스트림을 통해 네트워크 연결의 데이터를 읽고, 출력 스트림을 통해 로컬 데이터를 원격 엔드로 전송합니다.
소켓 연결은 실제로 파일 스트림 처리와 다소 유사하며 둘 다 IO 작업을 수행합니다.
입력 및 출력 스트림을 얻는 코드는 다음과 같습니다.
// 输入流 InputStream in = socket.getInputStream(); // 输出流 OutputStream out = socket.getOutputStream();
다음은 처리를 위한 입력 및 출력 패키징 클래스로
를 사용합니다.BufferedReader
与 PrintWriter
// 获取 socket 输入流 private BufferedReader getReader(Socket socket) throws IOException { InputStream in = socket.getInputStream(); return new BufferedReader(new InputStreamReader(in)); } // 获取 socket 输出流 private PrintWriter getWriter(Socket socket) throws IOException { OutputStream out = socket.getOutputStream(); return new PrintWriter(new OutputStreamWriter(out)); }
소켓 연결과 IO 입력 및 출력 스트림을 사용하여 요청 데이터를 보내고 요청의 응답 결과를 얻을 차례입니다.
IO 패키징 클래스의 지원으로 문자열 형식으로 직접 전송할 수 있으며 패키징 클래스는 데이터를 해당 바이트 스트림으로 변환하는 데 도움이 됩니다.
우리는 HTTP를 통해 바이두 사이트에 접속하기 때문에 추가적인 출력 형식을 정의할 필요가 없습니다. 표준 HTTP 전송 형식을 사용하면 요청 응답을 수행할 수 있습니다(일부 특정 RPC 프레임워크에는 사용자 정의된 통신 형식이 있을 수 있음).
요청된 데이터 내용은 다음과 같이 처리됩니다.
public class HttpUtil { public static String compositeRequest(String host){ return "GET / HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "User-Agent: curl/7.43.0\r\n" + "Accept: */*\r\n\r\n"; } }
// 发起请求 PrintWriter writer = getWriter(socket); writer.write(HttpUtil.compositeRequest(host)); writer.flush(); 接收响应数据代码如下: // 读取响应 String msg; BufferedReader reader = getReader(socket); while ((msg = reader.readLine()) != null){ System.out.println(msg); }
전체 코드는 다음과 같습니다.
import java.io.*; import java.net.InetSocketAddress; import java.net.Socket; import java.net.SocketAddress; import com.test.network.util.HttpUtil; public class SocketHttpClient { public void start(String host, int port) { // 初始化 socket Socket socket = new Socket(); try { // 设置 socket 连接 SocketAddress remote = new InetSocketAddress(host, port); socket.setSoTimeout(5000); socket.connect(remote); // 发起请求 PrintWriter writer = getWriter(socket); System.out.println(HttpUtil.compositeRequest(host)); writer.write(HttpUtil.compositeRequest(host)); writer.flush(); // 读取响应 String msg; BufferedReader reader = getReader(socket); while ((msg = reader.readLine()) != null){ System.out.println(msg); } } catch (IOException e) { e.printStackTrace(); } finally { try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } } private BufferedReader getReader(Socket socket) throws IOException { InputStream in = socket.getInputStream(); return new BufferedReader(new InputStreamReader(in)); } private PrintWriter getWriter(Socket socket) throws IOException { OutputStream out = socket.getOutputStream(); return new PrintWriter(new OutputStreamWriter(out)); } }
public class Application { public static void main(String[] args) { new SocketHttpClient().start("www.baidu.com", 80); } }
이렇게 하면 기능 구현에는 문제가 없지만. 하지만 자세히 살펴보면 IO 쓰기 및 읽기 프로세스 중에 IO 차단이 발생하는 것을 알 수 있습니다. 즉,
// 会发生 IO 阻塞 writer.write(HttpUtil.compositeRequest(host)); reader.readLine();
public class SingleThreadApplication { public static void main(String[] args) { // HttpConstant.HOSTS 为 站点集合 for (String host: HttpConstant.HOSTS) { new SocketHttpClient().start(host, HttpConstant.PORT); } } }
이것은 서버 측에서 더 분명합니다. 여기의 코드는 클라이언트 연결이지만 구체적인 작업은 서버 측의 코드와 유사합니다. 요청은 하나씩 순차적으로만 처리할 수 있으므로 응답 시간 표준을 확실히 충족할 수 없습니다.
public class MultiThreadApplication { public static void main(String[] args) { for (final String host: HttpConstant.HOSTS) { Thread t = new Thread(new Runnable() { public void run() { new SocketHttpClient().start(host, HttpConstant.PORT); } }); t.start(); } } }
public class ThreadPoolApplication { public static void main(String[] args) { ExecutorService executorService = Executors.newFixedThreadPool(8); for (final String host: HttpConstant.HOSTS) { Thread t = new Thread(new Runnable() { public void run() { new SocketHttpClient().start(host, HttpConstant.PORT); } }); executorService.submit(t); new SocketHttpClient().start(host, HttpConstant.PORT); } } }
이 방법이 최적인 것 같습니다. 스레드가 동시에 여러 소켓 연결을 처리할 수 있고 각 소켓의 입력 및 출력 데이터가 준비되지 않은 경우 차단하지 않으면 더 좋은 것이 있습니까? 이 기술을 "IO 다중화"라고 합니다. 해당 구현은 JAVA의 nio 패키지에 제공됩니다.
위 내용은 Java가 기본 소켓 통신 메커니즘을 구현하는 방법의 원리에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!