이 기사에서는 주로 JAVA에서 네이티브 소켓 통신 메커니즘을 구현하는 원리를 소개합니다. 편집자는 이것이 꽤 좋다고 생각하므로 지금 공유하고 참고용으로 제공하겠습니다. 편집자를 따라가서 살펴보겠습니다. 이 기사에서는 JAVA의 기본 소켓 통신 메커니즘을 소개하고 이를 모든 사람과 공유합니다.
현재 환경
jdk == 1.8
- 소켓 연결 처리
- IO 입출력 스트림 처리
- 요청 데이터 형식 처리
- 요청 모델 최적화
오늘은 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();
IO 스트림 처리와 관련하여 일반적으로 해당 패키징 클래스를 사용하여 IO 스트림을 처리하는 경우 바이트 단위로 작업해야 합니다. [], 이는 상대적으로 지루한 작업입니다. 래퍼 클래스를 사용하면 이를 string 및 int와 같은 유형으로 직접 처리할 수 있으므로 IO 바이트 작업이 단순화됩니다.
다음은 처리를 위한 입력 및 출력 패키징 클래스로
를 사용합니다.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();
따라서 10개의 다른 사이트를 동시에 요청하려면 다음과 같이 하세요.
public class SingleThreadApplication { public static void main(String[] args) { // HttpConstant.HOSTS 为 站点集合 for (String host: HttpConstant.HOSTS) { new SocketHttpClient().start(host, HttpConstant.PORT); } } }
첫 번째 요청 응답이 완료된 후 다음 사이트 처리가 시작되어야 합니다.
이것은 서버 측에서 더 분명합니다. 여기의 코드는 클라이언트 연결이지만 구체적인 작업은 서버 측의 코드와 유사합니다. 요청은 하나씩 순차적으로만 처리할 수 있으므로 응답 시간 표준을 확실히 충족할 수 없습니다.
- 멀티스레딩
- 어떤 사람들은 이것이 전혀 문제가 되지 않는다고 생각하는데, JAVA는 멀티스레드 프로그래밍 언어입니다. 이러한 상황에는 멀티스레드 모델이 가장 적합합니다.
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); } } }
시작된 스레드 수와 관련하여 일반적으로 CPU 집약적 유형은 N+1(N은 CPU 코어 수)로 설정되고, IO 집약적 유형은 2N+1로 설정됩니다.
이 방법이 최적인 것 같습니다. 스레드가 동시에 여러 소켓 연결을 처리할 수 있고 각 소켓의 입력 및 출력 데이터가 준비되지 않은 경우 차단하지 않으면 더 좋은 것이 있습니까? 이 기술을 "IO 다중화"라고 합니다. 해당 구현은 JAVA의 nio 패키지에 제공됩니다.
위 내용은 Java가 기본 소켓 통신 메커니즘을 구현하는 방법의 원리에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

이 기사에서는 Java 프로젝트 관리, 구축 자동화 및 종속성 해상도에 Maven 및 Gradle을 사용하여 접근 방식과 최적화 전략을 비교합니다.

이 기사에서는 Maven 및 Gradle과 같은 도구를 사용하여 적절한 버전 및 종속성 관리로 사용자 정의 Java 라이브러리 (JAR Files)를 작성하고 사용하는 것에 대해 설명합니다.

이 기사는 카페인 및 구아바 캐시를 사용하여 자바에서 다단계 캐싱을 구현하여 응용 프로그램 성능을 향상시키는 것에 대해 설명합니다. 구성 및 퇴거 정책 관리 Best Pra와 함께 설정, 통합 및 성능 이점을 다룹니다.

이 기사는 캐싱 및 게으른 하중과 같은 고급 기능을 사용하여 객체 관계 매핑에 JPA를 사용하는 것에 대해 설명합니다. 잠재적 인 함정을 강조하면서 성능을 최적화하기위한 설정, 엔티티 매핑 및 모범 사례를 다룹니다. [159 문자]

Java의 클래스 로딩에는 부트 스트랩, 확장 및 응용 프로그램 클래스 로더가있는 계층 적 시스템을 사용하여 클래스로드, 링크 및 초기화 클래스가 포함됩니다. 학부모 위임 모델은 핵심 클래스가 먼저로드되어 사용자 정의 클래스 LOA에 영향을 미치도록합니다.


핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

맨티스BT
Mantis는 제품 결함 추적을 돕기 위해 설계된 배포하기 쉬운 웹 기반 결함 추적 도구입니다. PHP, MySQL 및 웹 서버가 필요합니다. 데모 및 호스팅 서비스를 확인해 보세요.

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

MinGW - Windows용 미니멀리스트 GNU
이 프로젝트는 osdn.net/projects/mingw로 마이그레이션되는 중입니다. 계속해서 그곳에서 우리를 팔로우할 수 있습니다. MinGW: GCC(GNU Compiler Collection)의 기본 Windows 포트로, 기본 Windows 애플리케이션을 구축하기 위한 무료 배포 가능 가져오기 라이브러리 및 헤더 파일로 C99 기능을 지원하는 MSVC 런타임에 대한 확장이 포함되어 있습니다. 모든 MinGW 소프트웨어는 64비트 Windows 플랫폼에서 실행될 수 있습니다.

PhpStorm 맥 버전
최신(2018.2.1) 전문 PHP 통합 개발 도구

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.
