zoukankan      html  css  js  c++  java
  • [Java] 网络编程

    网络连接

    • 目的:实现不同主机间数据的共享,早期是主动共享,现在是被动共享
    • OSI七层模型,TCP五层模型,所有数据在每一层上进行信息处理,最终通过物理设备(网卡)发送,网卡在整个网络中有唯一的Mac地址
    • 网络编程:正对于TCP/UDP两种协议进行的网络开发,两个协议的细节组成非常繁琐,对网络协议的抽象性管理逻辑称为Socket编程
    • Socket内部两种模式
      • C/S(Client/Server):需要开发两套程序,一套服务器程序,一套客户端程序,在进行维护的时候服务器端和客户端的程序都需要更新(如QQ),使用特定的数据传输协议(用户自定义)及一些非公开端口,安全性较高
      • B/S(Browser/Server):基于浏览器实现客户端应用,只需要开发服务器端的程序,如需进行维护只需修改服务器代码,维护与开发成本降低,使用公共的HTTP协议(基于TCP协议的实现),所以安全性较差
    • 网络编程属于C/S模型,Web开发属于B/S模型
    • C/S模型分为
      • TCP程序:三次握手,四次挥手
      • UDP程序:发送数据报,接收数据报的一方不一定可以接收到数据(发短信,手机关机)

     

     

    网络程序

    •  java.net包完成,提供两个类
      • java.net.ServerSocket:工作在服务器端的程序类,定义服务器监听端口,及接收客户端请求
      • java.net.Socket:每一个客户端都使用一个Socket的概念进行描述
    • 端口是进入服务的“门”,每个端口只能绑定一个服务,建议用5000以上
    • 连接的目的是进行IO通讯

    服务器端程序

    • 验证服务器是否可正常使用,可利用操作系统中的telnet命令
    • 传输字节数据,用PrintStream
    • win+R > Telnet > open localhost 9999
    • telnet 仅是基础测试环境,不是客户端
    • 服务器端数据的输出,就是客户端数据的输入
    • accept():打开服务器监听
     1 import java.io.PrintStream;
     2 import java.net.ServerSocket;
     3 import java.net.Socket;
     4 
     5 public class HelloServer {
     6     public static void main(String[] args) throws Exception{
     7         ServerSocket serversocket = new ServerSocket(9999); // 本程序在9999端口连接
     8         System.out.println("[HelloServer] 服务器端启动监听... ...");
     9         // 每一个连接到服务器端的客户端都通过Socket对象来描述,所以要等待连接
    10         Socket client = serversocket.accept(); // 等待客户端连接
    11         // 向指定的Socket实现数据的输出,获取Socket的输出流
    12         PrintStream out = new PrintStream(client.getOutputStream()); // 通过打印流输出
    13         out.println("www.yootk.com"); // 输出信息
    14         client.shutdownOutput(); // 数据发送完毕后再关闭
    15         serversocket.close(); // 关闭整个服务器
    16     }
    17 }
    View Code

    客户端程序

    • Socket类描述的就属于客户端信息,在客户端主要用它来实现服务器端的连接,而服务器端每个连接到服务器的客户都通过Socket来描述
     1 import java.net.Socket;
     2 import java.util.Scanner;
     3 
     4 public class HelloClient {
     5     public static void main(String[] args) throws Exception{
     6         // Socket是工作在客户端的程序类,每一个Socket对象描述的都是一个独立的客户端
     7         Socket client = new Socket("localhost",9999);
     8         Scanner scanner = new Scanner(client.getInputStream()); // 服务器端的输出为客户端的输入
     9         if(scanner.hasNext()) { // 此时有数据需要进行输出
    10             System.out.println("[HelloClient] "+scanner.next());
    11         }
    12         client.shutdownInput();
    13     }
    14 }
    View Code

    Echo模型

    • 网络通讯程序的核心接口
    • 客户端发送数据给服务器端,服务器端接收到数据后直接进行回应
    • 回应处理可持续进行,当客户端确认不再继续交互时断开
    • Socket可获取InputStream、OutputStream
    • 实现最为核心的网络接口交互模型,再继续扩展可实现更加丰富内容的传输

    服务器端程序

     1 import java.io.PrintStream;
     2 import java.net.ServerSocket;
     3 import java.net.Socket;
     4 import java.util.Scanner;
     5 
     6 public class EchoServer {
     7     public static void main(String[] args) throws Exception{
     8         ServerSocket serversocket = new ServerSocket(9999);
     9         Socket client = serversocket.accept(); // 进入阻塞状态,等待客户端连接
    10         Scanner scanner = new Scanner(client.getInputStream()); // 服务器端输入流
    11         PrintStream out = new PrintStream(client.getOutputStream()); // 服务器端输出流
    12         boolean flag = true; 
    13         while(flag) {
    14             if(scanner.hasNext()) { // 如果现在有输入的数据内容
    15                 String value = scanner.next().trim();
    16                 if(value.equalsIgnoreCase("exit")) {
    17                     out.println("[EchoServer]exit");
    18                     flag = false;
    19                     break;
    20                 }
    21                 out.println("ECHO:"+ value);
    22             }
    23         }
    24         serversocket.close();
    25     }
    26 }
    View Code

    客户端程序

     1 import java.io.PrintStream;
     2 import java.net.Socket;
     3 import java.util.Scanner;
     4 
     5 public class EchoClient {
     6     public static void main(String[] args) throws Exception{
     7         Socket client = new Socket("localhost",9999);
     8         Scanner scanner = new Scanner(client.getInputStream()); // 客户端输入流
     9         PrintStream out = new PrintStream(client.getOutputStream()); // 客户端输出流
    10         boolean flag = true;
    11         while(flag) {
    12             String value = KeyboardInput.getString("请输入数据:");
    13             out.println(value);
    14             if(scanner.hasNext()) {
    15                 System.out.println("[ECHO客户端]" + scanner.next()); //服务器端响应
    16             }
    17             if(value.equalsIgnoreCase("exit")){
    18                 flag = false;
    19             }
    20         }
    21         client.close();
    22     }
    23 }
    View Code

    BIO处理模型

    • BIO(Blocking IO、阻塞IO处理)是最为传统的一种网络通讯模型的统一描述,解决服务器的并发处理问题,ECHO模型属于单线程服务器的开发,即同一个时间段只能有一个线程进行访问
    • 创建新的线程处理类,包裹Socket对象
    • 问题:需要先连接,然后服务器分配线程对象,若此时客户端即使没有与服务器端产生任何交互,那么这个线程的连接也要维持着,面对高并发访问程序会导致性能浪费,为解决次问题创建了NIO模型

     

    服务器端

     1 import java.net.ServerSocket;
     2 import java.net.Socket;
     3 
     4 public class EchoServer {
     5     public static void main(String[] args) throws Exception{
     6         ServerSocket serversocket = new ServerSocket(9999);
     7         boolean flag = true; 
     8         while(flag) {
     9             Socket client = serversocket.accept();
    10             new Thread(new EchoHandle(client)).start();
    11         }
    12         serversocket.close();
    13     }
    14 }
    View Code

    服务器端线程类

     1 import java.io.PrintStream;
     2 import java.net.Socket;
     3 import java.util.Scanner;
     4 
     5 public class EchoHandle implements Runnable{
     6     private Socket client;
     7     public EchoHandle(Socket client) {
     8         this.client = client;
     9     }
    10     @Override
    11     public void run() {
    12         try {        
    13             Scanner scanner = new Scanner(client.getInputStream()); // 服务器端输入流
    14             PrintStream out = new PrintStream(client.getOutputStream()); // 服务器端输出流
    15             boolean flag = true; 
    16             while(flag) {
    17                 if(scanner.hasNext()) { // 如果现在有输入的数据内容
    18                     String value = scanner.next().trim();
    19                     if(value.equalsIgnoreCase("exit")) {
    20                         out.println("[EchoServer]exit");
    21                         flag = false;
    22                     }else {
    23                         out.println("ECHO:"+ value);
    24                     }
    25                 }
    26             }
    27             scanner.close();
    28             out.close();
    29             client.close();
    30         }catch(Exception e) {}
    31     }
    32 }
    View Code

    客户端

     1 import java.io.PrintStream;
     2 import java.net.Socket;
     3 import java.util.Scanner;
     4 
     5 public class EchoClient {
     6     public static void main(String[] args) throws Exception{
     7         Socket client = new Socket("localhost",9999);
     8         Scanner scanner = new Scanner(client.getInputStream()); // 客户端输入流
     9         PrintStream out = new PrintStream(client.getOutputStream()); // 客户端输出流
    10         boolean flag = true;
    11         while(flag) {
    12             String value = KeyboardInput.getString("请输入数据:");
    13             out.println(value);
    14             if(scanner.hasNext()) {
    15                 System.out.println("[ECHO客户端]" + scanner.next()); //服务器端响应
    16             }
    17             if(value.equalsIgnoreCase("exit")){
    18                 flag = false;
    19             }
    20         }
    21         scanner.close();
    22         out.close();
    23         client.close();
    24     }
    25 }
    View Code

    UDP程序

    • TCP:可靠连接模式,可保证接收稳定性,但会带来严重的性能损耗
    • UDP:不保证用户一定可以收到,但性能较高
    • 类比:发传单
    • 实例:手机短信(不开机收不到)
    • UDP客户端:等待服务器端进行消息数据的发送,如接收到内容则继续向下执行,进行具体内容输出
    • HTTP协议里可能将TCP协议更换
    • 用Netty开发更加简单

    服务器端

     1 import java.net.DatagramPacket;
     2 import java.net.DatagramSocket;
     3 import java.net.InetAddress;
     4 
     5 public class UDPServer {
     6     public static void main(String[] args) throws Exception{
     7         DatagramSocket server = new DatagramSocket(8000); // 服务器端端口
     8         String message = "www.yootk.com";
     9         DatagramPacket packet = new DatagramPacket(message.getBytes(),0,message.length(),InetAddress.getByName("localhost"),9999);
    10         server.send(packet); // 发送数据报
    11         System.out.println("[UDPServer]finished...");
    12         server.close();
    13     }
    14 }
    View Code

    客户端

     1 import java.net.DatagramPacket;
     2 import java.net.DatagramSocket;
     3 
     4 public class UDPClient {
     5     public static void main(String[] args) throws Exception{
     6         DatagramSocket client = new DatagramSocket(9999);
     7         byte data[] = new byte[1024];
     8         DatagramPacket packet = new DatagramPacket(data, data.length);
     9         System.out.println("[UDPClient]wait...");
    10         client.receive(packet);
    11         System.out.println("[UDPClient]"+ new String(data,0,packet.getLength()));
    12     }
    13 }
    View Code

  • 相关阅读:
    Max History CodeForces
    Buy a Ticket CodeForces
    AC日记——字符串的展开 openjudge 1.7 35
    AC日记——回文子串 openjudge 1.7 34
    AC日记——判断字符串是否为回文 openjudge 1.7 33
    AC日记——行程长度编码 openjudge 1.7 32
    AC日记——字符串P型编码 openjudge 1.7 31
    AC日记——字符环 openjudge 1.7 30
    AC日记——ISBN号码 openjudge 1.7 29
    AC日记——单词倒排 1.7 28
  • 原文地址:https://www.cnblogs.com/cxc1357/p/12460277.html
Copyright © 2011-2022 走看看