


Explication détaillée des principes selon lesquels Java implémente le mécanisme de communication par socket natif
Cet article présente principalement le principe d'implémentation du mécanisme de communication par socket natif en JAVA. L'éditeur pense que c'est plutôt bien, je vais donc le partager avec vous maintenant et le donner comme référence. Suivons l'éditeur et jetons un coup d'œil.
Cet article présente le principe du mécanisme de communication de socket natif en JAVA et le partage avec tout le monde. Les détails sont les suivants :
Environnement actuel.
jdk == 1.8
Points de connaissance
Traitement des connexions de socket
Traitement des flux d'entrée et de sortie IO
Traitement du format de données de demande
-
Optimisation du modèle de demande
Scénario
Aujourd'hui, parlons des problèmes de communication des sockets en JAVA. Nous prenons ici comme exemple le modèle le plus simple, une demande, une réponse, en supposant que nous devons maintenant communiquer avec le site Baidu. Comment pouvons-nous utiliser le socket natif de JAVA pour y parvenir ?
Établir une connexion socket
Tout d'abord, nous devons établir une connexion socket (code principal)
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);
Traitement des flux d'entrée et de sortie de socket
Après avoir réussi à établir une connexion de socket, nous pouvons obtenir ses flux d'entrée et de sortie. L'essence de la communication est le traitement. des flux d’entrée et de sortie. Grâce au flux d'entrée, les données de la connexion réseau sont lues et via le flux de sortie, les données locales sont envoyées à l'extrémité distante.
La connexion socket est en fait quelque peu similaire au traitement des flux de fichiers, les deux effectuent des opérations d'E/S.
Le code d'obtention des flux d'entrée et de sortie est le suivant :
// 输入流 InputStream in = socket.getInputStream(); // 输出流 OutputStream out = socket.getOutputStream();
Concernant le traitement des flux IO, nous utilisons généralement les classes de packaging correspondantes pour traiter les flux IO, s'ils sont traités directement, nous devons opérer sur byte[], ce qui est relativement fastidieux. Si nous utilisons une classe wrapper, nous pouvons la traiter directement avec des types tels que string et int, ce qui simplifie les opérations sur les octets IO.
est traité ci-dessous en utilisant BufferedReader
et PrintWriter
comme classes d'empaquetage d'entrée et de sortie.
// 获取 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)); }
Demande et réponse de données
Avec la connexion par socket et le flux d'entrée et de sortie IO, les éléments suivants devraient être fait Envoyer les données de la demande à et obtenir les résultats de la réponse à la demande.
Avec la prise en charge de la classe d'empaquetage IO, nous pouvons transmettre directement au format chaîne, et la classe d'empaquetage nous aidera à convertir les données en flux d'octets correspondant.
Étant donné que nous accédons au site baidu via HTTP, nous n'avons pas besoin de définir de formats de sortie supplémentaires. En utilisant le format de transmission HTTP standard, vous pouvez effectuer des réponses aux requêtes (certains frameworks RPC spécifiques peuvent avoir des formats de communication personnalisés).
Le contenu des données demandées est traité comme suit :
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"; } }
Le code d'envoi des données de la demande est le suivant :
// 发起请求 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); }
Jusqu'à présent, nous avons fini de parler de tous les codes de base pour créer des connexions, envoyer des requêtes et recevoir des réponses sous des sockets natifs.
Le code complet est le suivant :
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)); } }
Ci-dessous, nous montrons les résultats de la communication socket en instanciant un client.
public class Application { public static void main(String[] args) { new SocketHttpClient().start("www.baidu.com", 80); } }
Sortie du résultat :
Optimisation du modèle de demande
De cette façon, même s'il n'y a aucun problème pour réaliser la fonction. Mais lorsque nous y regardons de plus près, nous constatons que le blocage des E/S se produit pendant le processus d'écriture et de lecture des E/S. Soit :
// 会发生 IO 阻塞 writer.write(HttpUtil.compositeRequest(host)); reader.readLine();
Donc si vous souhaitez demander 10 sites différents en même temps, comme suit :
public class SingleThreadApplication { public static void main(String[] args) { // HttpConstant.HOSTS 为 站点集合 for (String host: HttpConstant.HOSTS) { new SocketHttpClient().start(host, HttpConstant.PORT); } } }
Il doit compléter la première réponse à la demande avant de lancer le traitement suivant du site.
Cela est plus évident côté serveur. Bien que le code ici soit une connexion client, les opérations spécifiques sont similaires à celles côté serveur. Les demandes ne peuvent être traitées qu'en série une par une, ce qui ne respectera certainement pas la norme de temps de réponse.
Multi-threading
Certaines personnes pensent que ce n'est pas du tout un problème, JAVA est un langage de programmation multi-thread. Dans cette situation, un modèle multithread est le plus approprié.
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(); } } }
Cette méthode semble utile au début, mais lorsque la quantité de concurrence est importante, l'application utilisera beaucoup de threads. Comme nous le savons tous, sur le serveur, chaque thread occupe en fait un descripteur de fichier. Le nombre de handles sur le serveur est limité et un grand nombre de threads entraînera une consommation considérable de commutation entre les threads. Par conséquent, cette méthode doit être insupportable dans les scénarios à forte concurrence.
Traitement multi-thread + pool de threads
Comme trop de threads ne suffisent pas, nous pouvons simplement contrôler le nombre de threads créés. Seul un nombre fixe de threads est démarré pour le traitement des sockets, qui utilise non seulement le traitement multithread, mais contrôle également la consommation des ressources du système.
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); } } }
Concernant le nombre de threads démarrés, généralement le type gourmand en CPU sera fixé à N+1 (N est le nombre de cœurs CPU), et le Le type intensif en IO sera défini sur 2N + 1 .
Cette méthode semble être la meilleure. Y a-t-il quelque chose de mieux ? Si un thread peut gérer plusieurs connexions de socket en même temps et ne se bloque pas lorsque les données d’entrée et de sortie de chaque socket ne sont pas prêtes, est-ce mieux ? Cette technologie est appelée « multiplexage IO ». L'implémentation correspondante est fournie dans le package nio de JAVA.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Outils d'IA chauds

Undresser.AI Undress
Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover
Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool
Images de déshabillage gratuites

Clothoff.io
Dissolvant de vêtements AI

AI Hentai Generator
Générez AI Hentai gratuitement.

Article chaud

Outils chauds

Bloc-notes++7.3.1
Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise
Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1
Puissant environnement de développement intégré PHP

Dreamweaver CS6
Outils de développement Web visuel

SublimeText3 version Mac
Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Guide du nombre parfait en Java. Nous discutons ici de la définition, comment vérifier le nombre parfait en Java ?, des exemples d'implémentation de code.

Guide du générateur de nombres aléatoires en Java. Nous discutons ici des fonctions en Java avec des exemples et de deux générateurs différents avec d'autres exemples.

Guide de Weka en Java. Nous discutons ici de l'introduction, de la façon d'utiliser Weka Java, du type de plate-forme et des avantages avec des exemples.

Guide du nombre de Smith en Java. Nous discutons ici de la définition, comment vérifier le numéro Smith en Java ? exemple avec implémentation de code.

Dans cet article, nous avons conservé les questions d'entretien Java Spring les plus posées avec leurs réponses détaillées. Pour que vous puissiez réussir l'interview.

Java 8 présente l'API Stream, fournissant un moyen puissant et expressif de traiter les collections de données. Cependant, une question courante lors de l'utilisation du flux est: comment se casser ou revenir d'une opération FOREAK? Les boucles traditionnelles permettent une interruption ou un retour précoce, mais la méthode Foreach de Stream ne prend pas directement en charge cette méthode. Cet article expliquera les raisons et explorera des méthodes alternatives pour la mise en œuvre de terminaison prématurée dans les systèmes de traitement de flux. Lire plus approfondie: Améliorations de l'API Java Stream Comprendre le flux Forach La méthode foreach est une opération terminale qui effectue une opération sur chaque élément du flux. Son intention de conception est

Guide de TimeStamp to Date en Java. Ici, nous discutons également de l'introduction et de la façon de convertir l'horodatage en date en Java avec des exemples.

Les capsules sont des figures géométriques tridimensionnelles, composées d'un cylindre et d'un hémisphère aux deux extrémités. Le volume de la capsule peut être calculé en ajoutant le volume du cylindre et le volume de l'hémisphère aux deux extrémités. Ce tutoriel discutera de la façon de calculer le volume d'une capsule donnée en Java en utilisant différentes méthodes. Formule de volume de capsule La formule du volume de la capsule est la suivante: Volume de capsule = volume cylindrique volume de deux hémisphères volume dans, R: Le rayon de l'hémisphère. H: La hauteur du cylindre (à l'exclusion de l'hémisphère). Exemple 1 entrer Rayon = 5 unités Hauteur = 10 unités Sortir Volume = 1570,8 unités cubes expliquer Calculer le volume à l'aide de la formule: Volume = π × r2 × h (4
