Connexion TCP
La base de TCP est Socket. Dans la connexion TCP, nous utiliserons ServerSocket et Socket une fois que le client et le serveur ont établi une connexion, le reste est essentiellement le contrôle des E/S.
Examinons d'abord une simple communication TCP, divisée en client et serveur.
Le code client est le suivant :
public static void main (String[] args) lance IOException
{
Socket socket = nul ;
BufferedReader br = null ;
Mot de passe PrintWriter = null ;
BufferedReader brTemp = null ;
essayer
{
socket = new Socket(InetAddress.getLocalHost(), 5678);
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
pw = new PrintWriter(socket.getOutputStream());
brTemp = nouveau BufferedReader (nouveau InputStreamReader (System.in));
tandis que (vrai)
{
Ligne de chaîne = brTemp.readLine();
pw.println(ligne);
pw.flush();
if (line.equals("end")) break;
System.out.println(br.readLine());
}
}
attraper (exception ex)
{
System.err.println(ex.getMessage());
}
enfin
{
if (socket != null) socket.close();
if (br != null) br.close();
if (brTemp != null) brTemp.close();
if (pw != null) pw.close();
}
}
}
public static void main (String[] args) lance IOException
{
Serveur ServerSocket = nul ;
Client de socket = nul ;
BufferedReader br = null ;
Mot de passe PrintWriter = null ;
essayer
{
serveur = nouveau ServerSocket (5678);
client = serveur.accepter();
br = new BufferedReader(new InputStreamReader(client.getInputStream()));
pw = new PrintWriter(client.getOutputStream());
tandis que (vrai)
{
Ligne de chaîne = br.readLine();
pw.println("Réponse :" + ligne);
pw.flush();
if (line.equals("end")) break;
}
}
attraper (exception ex)
{
System.err.println(ex.getMessage());
}
enfin
{
if (server != null) server.close();
if (client != null) client.close();
if (br != null) br.close();
if (pw != null) pw.close();
}
}
}
Le code ci-dessus décrit essentiellement le cadre principal du client et du serveur pendant le processus de communication TCP. Nous pouvons constater que dans le code ci-dessus, le serveur ne peut traiter qu'une seule requête du client à la fois. ne peut pas être parallélisé. Ce n'est pas la même chose que la méthode de traitement du serveur dans notre impression. Nous pouvons ajouter du multi-thread au serveur lorsqu'une requête client arrive, nous créons un thread pour traiter la requête correspondante.
Le code amélioré côté serveur est le suivant :
la classe ServerThread étend Thread
{
socket privé socket = null ;
public ServerThread (socket)
{
this.socket = socket;
}
public void run() {
BufferedReader br = null ;
Mot de passe PrintWriter = null ;
essayer
{
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
pw = new PrintWriter(socket.getOutputStream());
tandis que (vrai)
{
Ligne de chaîne = br.readLine();
pw.println("Réponse :" + ligne);
pw.flush();
if (line.equals("end")) break;
}
}
attraper (exception ex)
{
System.err.println(ex.getMessage());
}
enfin
{
si (socket != nul)
essayer {
socket.close();
} catch (IOException e1) {
e1.printStackTrace();
}
si (br != nul)
essayer {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
if (pw != null) pw.close();
}
}
}
Dans le processus de programmation, nous avons le concept de « ressource ». Par exemple, la connexion à la base de données est une ressource typique. Afin d'améliorer les performances, nous ne détruisons généralement pas la connexion à la base de données directement, mais utilisons le pool de connexions à la base de données pour en gérer plusieurs. les bases de données. Les connexions sont gérées et réutilisées. Pour les connexions Socket, c'est aussi une ressource. Lorsque notre programme nécessite un grand nombre de connexions Socket, ce sera une approche très inefficace si chaque connexion doit être rétablie.
Semblable au pool de connexions à la base de données, nous pouvons également concevoir un pool de connexions TCP. L'idée ici est d'utiliser un tableau pour maintenir plusieurs connexions Socket et un autre tableau d'état pour décrire si chaque connexion Socket est utilisée lorsque le programme nécessite un pool de connexions. Connexion Socket, nous parcourons le tableau d'état et supprimons la première connexion Socket inutilisée. Si toutes les connexions sont utilisées, une exception est levée. Il s'agit d'une "stratégie de planification" très intuitive et simple. Dans de nombreux frameworks open source ou commerciaux (Apache/Tomcat), il y aura des "pools de ressources" similaires.
Le code du pool de connexions TCP est le suivant :
adresse InetAddress privée = null ;
port international privé;
private Socket[] arrSockets = null;
private boolean[] arrStatus = null;
nombre d'ints privés ;
public TcpConnectionPool (adresse InetAddress, port int, nombre int)
{
this.address = adresse ;
ceci.port = port ;
ce .count = count ;
arrSockets = nouveau Socket[nombre];
arrStatus = nouveau booléen[compte];
init();
}
initialisation vide privée()
{
essayer
{
pour (int i = 0; i < nombre; i++)
{
arrSockets[i] = new Socket(address.getHostAddress(), port);
arrStatus[i] = faux ;
}
}
attraper (exception ex)
{
System.err.println(ex.getMessage());
}
}
Prise publique getConnection()
{
if (arrSockets == null) init();
int je = 0;
pour(i = 0; i < nombre; i++)
{
si (arrStatus[i] == faux)
{
arrStatus[i] = vrai ;
casser;
}
}
if (i == count) throw new RuntimeException("aucune connexion n'est disponible pour l'instant.");
retourner arrSockets[i];
}
public void releaseConnection (Socket socket)
{
if (arrSockets == null) init();
pour (int i = 0; i < nombre; i++)
{
si (arrSockets[i] == socket)
{
arrStatus[i] = faux ;
casser;
}
}
}
reBuild public vide()
{
init();
}
public void détruire()
{
if (arrSockets == null) return ;
pour (int i = 0; i < nombre; i++)
{
essayer
{
arrSockets[i].close();
}
attraper (exception ex)
{
System.err.println(ex.getMessage());
continuer;
}
}
}
}
UDP est une méthode de connexion différente de TCP. Elle est généralement utilisée dans des situations nécessitant des performances en temps réel élevées et de faibles exigences de précision, comme la vidéo en ligne. UDP aura une "perte de paquets". Dans TCP, si le serveur n'est pas démarré, une exception sera signalée lorsque le client envoie un message, mais pour UDP, aucune exception ne sera générée.
Les deux classes utilisées pour la communication UDP sont DatagramSocket et DatagramPacket, cette dernière stocke le contenu de la communication.
Ce qui suit est un exemple simple de communication UDP. Comme TCP, il est également divisé en deux parties : Client et Serveur. Le code client est le suivant :
public static void main (String[] arguments)
{
essayer
{
Hôte InetAddress = InetAddress.getLocalHost();
port entier = 5678 ;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
tandis que (vrai)
{
Ligne de chaîne = br.readLine();
byte[] message = line.getBytes();
Paquet DatagramPacket = nouveau DatagramPacket (message, message.longueur, hôte, port) ;
Prise DatagramSocket = new DatagramSocket();
socket.send (paquet);
socket.close();
if (line.equals("end")) break;
}
br.close();
}
attraper (exception ex)
{
System.err.println(ex.getMessage());
}
}
}
public static void main (String[] arguments)
{
essayer
{
port entier = 5678 ;
DatagramSocket dsSocket = nouveau DatagramSocket(port);
octet[] tampon = nouvel octet[1024];
Paquet DatagramPacket = new DatagramPacket (buffer, buffer.length);
tandis que (vrai)
{
dsSocket.receive(paquet);
Message de chaîne = new String(buffer, 0, packet.getLength());
System.out.println(packet.getAddress().getHostName() + ":" + message);
if (message.equals("end")) break;
paquet.setLength(buffer.length);
}
dsSocket.close();
}
attraper (exception ex)
{
System.err.println(ex.getMessage());
}
}
}
La multidiffusion utilise une méthode similaire à UDP. Elle utilise des adresses IP de classe D et les numéros de port UDP standard font référence aux adresses comprises entre 224.0.0.0 et 239.255.255.255, à l'exclusion de 224.0.0.0.
La classe utilisée en multidiffusion est MulticastSocket, qui comporte deux méthodes auxquelles il faut prêter attention : joinGroup et LeaveGroup.
Voici un exemple de multidiffusion. Le code client est le suivant :
public static void main (String[] arguments)
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
essayer
{
Adresse InetAddress = InetAddress.getByName("230.0.0.1");
port entier = 5678 ;
tandis que (vrai)
{
Ligne de chaîne = br.readLine();
byte[] message = line.getBytes();
Paquet DatagramPacket = nouveau DatagramPacket (message, message.longueur, adresse, port) ;
MulticastSocket multicastSocket = new MulticastSocket();
multicastSocket.send(paquet);
if (line.equals("end")) break;
}
br.close();
}
attraper (exception ex)
{
System.err.println(ex.getMessage());
}
}
}
public static void main (String[] arguments)
{
port entier = 5678 ;
essayer
{
MulticastSocket multicastSocket = nouveau MulticastSocket(port);
Adresse InetAddress = InetAddress.getByName("230.0.0.1");
multicastSocket.joinGroup(adresse);
octet[] tampon = nouvel octet[1024];
Paquet DatagramPacket = new DatagramPacket (buffer, buffer.length);
tandis que (vrai)
{
multicastSocket.receive(paquet);
Message de chaîne = new String(buffer, packet.getLength());
System.out.println(packet.getAddress().getHostName() + ":" + message);
if (message.equals("end")) break;
paquet.setLength(buffer.length);
}
multicastSocket.close();
}
attraper (exception ex)
{
System.err.println(ex.getMessage());
}
}
}
NIO est un nouvel ensemble d'API IO introduit dans JDK1.4. Il présente de nouvelles conceptions en matière de gestion des tampons, de communication réseau, d'accès aux fichiers et d'opérations de jeu de caractères. Pour la communication réseau, NIO utilise les concepts de tampons et de canaux.
Ce qui suit est un exemple de NIO, qui est très différent du style de codage mentionné ci-dessus.
public static void main (String[] arguments)
{
Chaîne hôte="127.0.0.1" ;
port entier = 5678 ;
Canal SocketChannel = nul ;
essayer
{
Adresse InetSocketAddress = new InetSocketAddress(hôte,port);
Jeu de caractères charset = Charset.forName("UTF-8");
CharsetDecoder décodeur = charset.newDecoder();
Encodeur CharsetEncoder = charset.newEncoder();
Tampon ByteBuffer = ByteBuffer.allocate(1024);
CharBuffer charBuffer = CharBuffer.allocate(1024);
canal = SocketChannel.open();
canal.connect(adresse);
Requête de chaîne = "GET / /r/n/r/n" ;
canal.write(encoder.encode(CharBuffer.wrap(request)));
while((channel.read(buffer)) != -1)
{
tampon.flip();
decoder.decode(buffer, charBuffer, false);
charBuffer.flip();
System.out.println(charBuffer);
tampon.clear();
charBuffer.clear();
}
}
attraper (exception ex)
{
System.err.println(ex.getMessage());
}
enfin
{
si (canal != null)
essayer {
canal.close();
} catch (IOException e) {
// TODO Bloc catch généré automatiquement
e.printStackTrace();
}
}
}
}