第十六章 网络编程

作者: 永不熄灭的火焰_e306 | 来源:发表于2019-12-01 15:22 被阅读0次

网络编程

一、InetAddress

封装计算机的ip地址 ,没有端口。

 //使用getLocalHost方法创建InetAddress对象
 InetAddress addr = InetAddress.getLocalHost();
 System.out.println(addr.getHostAddress()); //返回:192.168.1.110
 System.out.println(addr.getHostName()); //输出计算机名
 ​
 //根据域名得到InetAddress对象
 addr = InetAddress.getByName(“www.163.com”); 
 System.out.println(addr.getHostAddress()); //返回 163服务器的ip:61.135.253.15  (因为咱们没有解析域名的权利,这个是由DNS来解析的)
 System.out.println(addr.getHostName()); //输出:www.163.com
 //根据ip得到InetAddress对象
 addr = InetAddress.getByName(“61.135.253.15”); 
 System.out.println(addr.getHostAddress()); //返回 163服务器的ip:61.135.253.15
 System.out.println(addr.getHostName()); //输出ip而不是域名。如果这个IP地 址不存在或DNS服务器不允许进行IP地址和域名的映射,getHostName方法就直接返回这个IP地
 址。

二、InetSocketAddress

包含端口,用于socket通信的

 //包含端口
 InetSocketAddress socketAddress = new InetSocketAddress("127.0.0.1",8080);
 InetSocketAddress socketAddress2 = new InetSocketAddress(“localhost”,9000);
 System.out.println(socketAddress.getHostName());
 System.out.println(socketAddress2.getAddress());

1 关于URI

URI: Universal Resource Identifier 统一资源标志符,用
来标识抽象或物理资源的一个紧凑字符串。
• URL:Universal Resource Locator 统一资源定位符,一种定
位资源的主要访问机制的字符串,一个标准的URL必须包括:
protocol、host、port、path、parameter、anchor。
• URN:Universal Resource Name 统一资源名称,通过特定命名
空间中的唯一名称或ID来标识资源。</pre>

http://www.google.com:80/index.html 由四部分组成

协议 存放资源的主机域名 端口号 资源文件名

关于URL
 URL u = new URL("http://www.baidu.con:80/index.html#aa?cansu=shsxt");
 System.out.println("获取与此url关联的协议的默认端口:
 "+u.getDefaultPort());
 System.out.println(“getFile:”+u.getFile()); //端口号后面的内容
 System.out.println("主机名:"+u.getHost()); //www.baidu.com
 System.out.println(“路径:”+u.getPath()); //端口号后,参数前的内容
 System.out.println(“端口:”+u.getPort()); //存在返回80.否则返回-1
 System.out.println("协议:"+u.getProtocol()); 
 System.out.println("参数部分:"+u.getQuery()); 
 System.out.println("锚点:"+u.getRef()); 
 URL u = new URL("http://www.abc.com/aa/");
 URL u2 = new URL(u,“2.html”); //相对路径构建url对象
 System.out.println(u2.toString()); //http://www.abc.com/aa/2.html
相关API
API.png

三、传输协议 TCP、UDP

1 UDP

种无连接的传输层协议,提供面向事 务的简单不可靠信息传送服务

特点

非面向连接,传输不可靠,可能丢失

发送不管对方是否准备好,接收方收 到也不确认

可以广播发送

非常简单的协议,开销小

基本操作

 //接收方
 /**
  * 基本流程: 接收端
  * Address already in use: Cannot bind  同一个协议下端口不允许冲突
  * 1、使用DatagramSocket  指定端口 创建接收端
  * 2、准备容器 封装成DatagramPacket 包裹
  * 3、阻塞式接收包裹receive•(DatagramPacket p)
  * 4、分析数据
  *    byte[]  getData•()
  *                getLength•()
  * 5、释放资源
  * @author 裴新 QQ:3401997271
  *
  */
 public class UdpServer {
 ​
  public static void main(String[] args) throws Exception {
  System.out.println("接收方启动中.....");
  // 1、使用DatagramSocket  指定端口 创建接收端
  DatagramSocket server =new DatagramSocket(6666);
  // 2、准备容器 封装成DatagramPacket 包裹
  byte[] container =new byte[1024*60];
  DatagramPacket packet = new DatagramPacket(container,0,container.length);
  // 3、阻塞式接收包裹receive•(DatagramPacket p)
  server.receive(packet); //阻塞式
  // 4、分析数据
  //    byte[]  getData•()
  //                getLength•()
  byte[]  datas =packet.getData();
  int len = packet.getLength();
  System.out.println(new String(datas,0,len));

  // 5、释放资源
  server.close();
  }
 ​
 }
 //发送方
 /**
  * 基本流程: 发送端
  * 1、使用DatagramSocket  指定端口 创建发送端
  * 2、准备数据 一定转成字节数组
  * 3、 封装成DatagramPacket 包裹,需要指定目的地
  * 4、发送包裹send•(DatagramPacket p) * 
  * 5、释放资源
  * @author 裴新 QQ:3401997271
  *
  */
 public class UdpClient {
 ​
  public static void main(String[] args) throws Exception {
  System.out.println("发送方启动中.....");
  // 1、使用DatagramSocket  指定端口 创建发送端
  DatagramSocket client =new DatagramSocket(8888);
  //2、准备数据 一定转成字节数组
  String data = "上海尚学堂";
  byte[] datas = data.getBytes();
  //3、 封装成DatagramPacket 包裹,需要指定目的地
  DatagramPacket packet =new DatagramPacket(datas,0,datas.length,
  new InetSocketAddress("localhost",6666));
  //4、发送包裹send•(DatagramPacket p) * 
  client.send(packet);
  // 5、释放资源
  client.close();
  }
 ​
 }

文件传输

//服务器端--接收端
 /**
  * 文件存储: 接收端
  * Address already in use: Cannot bind  同一个协议下端口不允许冲突
  * 1、使用DatagramSocket  指定端口 创建接收端
  * 2、准备容器 封装成DatagramPacket 包裹
  * 3、阻塞式接收包裹receive•(DatagramPacket p)
  * 4、分析数据    将字节数组还原为对应的类型
  *    byte[]  getData•()
  *                getLength•()
  * 5、释放资源
  * @author 裴新 QQ:3401997271
  *
  */
 public class UdpFileServer {
 ​
  public static void main(String[] args) throws Exception {
  System.out.println("接收方启动中.....");
  // 1、使用DatagramSocket  指定端口 创建接收端
  DatagramSocket server =new DatagramSocket(6666);
  // 2、准备容器 封装成DatagramPacket 包裹
  byte[] container =new byte[1024*60];
  DatagramPacket packet = new DatagramPacket(container,0,container.length);
  // 3、阻塞式接收包裹receive•(DatagramPacket p)
  server.receive(packet); //阻塞式
  // 4、分析数据    将字节数组还原为对应的类型
  //    byte[]  getData•()
  //                getLength•()
  byte[]  datas =packet.getData();
  int len = packet.getLength(); 
  IOUtils.byteArrayToFile(datas, "src/copy.png"); 
  // 5、释放资源
  server.close();
  }
 ​
 }
 ​
 //客户端--发送方
 /**
  *  文件上传: 发送端
  * 1、使用DatagramSocket  指定端口 创建发送端
  * 2、将基本类型  转成字节数组
  * 3、 封装成DatagramPacket 包裹,需要指定目的地
  * 4、发送包裹send•(DatagramPacket p) * 
  * 5、释放资源
  * @author 裴新 QQ:3401997271
  *
  */
 public class UdpFileClient {
 ​
  public static void main(String[] args) throws Exception {
  System.out.println("发送方启动中.....");
  // 1、使用DatagramSocket  指定端口 创建发送端
  DatagramSocket client =new DatagramSocket(8888);
  //2、准备数据 一定转成字节数组
  byte[] datas =IOUtils.fileToByteArray("src/logo.png"); 
  //3、 封装成DatagramPacket 包裹,需要指定目的地
  DatagramPacket packet =new DatagramPacket(datas,0,datas.length,
  new InetSocketAddress("localhost",6666));
  //4、发送包裹send•(DatagramPacket p) * 
  client.send(packet);
  // 5、释放资源
  client.close();
  }
 ​
 }

双方交流

 /**
  * 接收端: 使用面向对象封装
  * 
  * @author 裴新 QQ:3401997271
  *
  */
 public class TalkReceive implements Runnable {
  private DatagramSocket server ;
  private String from ;
  public TalkReceive(int port,String from) {
  this.from = from ;
  try {
  server=new DatagramSocket(port);
  } catch (SocketException e) {
  e.printStackTrace();
  }
  }
  @Override
  public void run() {
  while(true) {
  // 2、准备容器 封装成DatagramPacket 包裹
  byte[] container =new byte[1024*60];
  DatagramPacket packet = new DatagramPacket(container,0,container.length);
  // 3、阻塞式接收包裹receive•(DatagramPacket p)
  try {
  server.receive(packet);//阻塞式
  // 4、分析数据
  byte[]  datas =packet.getData();
  int len = packet.getLength();
  String data=new String(datas,0,len);
  System.out.println(from+":"+data);
  if(data.equals("bye")) {
  break;
  }
  } catch (IOException e) {
  e.printStackTrace();
  } 
  }
  // 5、释放资源
  server.close();
  }
 ​
 }
 ​
 /**
  * 发送端: 使用面向对象封装
  * 
  * @author 裴新 QQ:3401997271
  *
  */
 public class TalkSend implements Runnable {
  private DatagramSocket client ;
  private BufferedReader reader;
  private String toIP ;
  private int toPort ;
  public TalkSend(int port,String toIP,int toPort) {
  this.toIP = toIP;
  this.toPort=toPort;
  try {
  client=new DatagramSocket(port);
  reader =new BufferedReader(new InputStreamReader(System.in));
  } catch (SocketException e) {
  e.printStackTrace();
  }
  }
  @Override
  public void run() {
  while(true) {
  String data;
  try {
  data = reader.readLine();
  byte[] datas = data.getBytes();
  //3、 封装成DatagramPacket 包裹,需要指定目的地
  DatagramPacket packet =new DatagramPacket(datas,0,datas.length,
  new InetSocketAddress(this.toIP,this.toPort));
  //4、发送包裹send•(DatagramPacket p) * 
  client.send(packet);
  if(data.equals("bye")) {
  break;
  }
  } catch (IOException e) {
  e.printStackTrace();
  }

  }
  // 5、释放资源
  client.close();
  }
 ​
 }
 ​
 //使用
 /**
  * 加入多线程,实现双向交流 模拟在线咨询
  * 
  * @author 裴新 QQ:3401997271
  *
  */
 public class TalkTeacher {
  public static void main(String[] args) {
  new Thread(new TalkReceive(9999,"学生")).start(); //接收

  new Thread(new TalkSend(5555,"localhost",8888)).start(); //发送
  }
 }
 -------------------------
 /**
  * 加入多线程,实现双向交流 模拟在线咨询
  * 
  * @author 裴新 QQ:3401997271
  *
  */
 public class TalkStudent {
  public static void main(String[] args) {
  new Thread(new TalkSend(7777,"localhost",9999)).start(); //发送 
  new Thread(new TalkReceive(8888,"老师")).start(); //接收
  }
 }

2 TCP

一种面向连接(连接导向)的、可靠的、基于字节流的运输层(Transport layer) 通信协议。

特点

面向连接

点到点的通信

高可靠性

占用系统资源多、效率低

基本使用
/**
  * 熟悉流程
  * 创建服务器
  * 1、指定端口 使用ServerSocket创建服务器
  * 2、阻塞式等待连接 accept
  * 3、操作: 输入输出流操作
  * 4、释放资源 
  * @author 裴新 QQ:3401997271
  *
  */
 public class Server {
 ​
  public static void main(String[] args) throws IOException {
  System.out.println("-----Server-----");
  // 1、指定端口 使用ServerSocket创建服务器
  ServerSocket server =new ServerSocket(8888);
  // 2、阻塞式等待连接 accept
  Socket  client =server.accept(); 
  System.out.println("一个客户端建立了连接");
  // 3、操作: 输入输出流操作
  DataInputStream dis =new DataInputStream(client.getInputStream());
  String data =dis.readUTF();
  System.out.println(data);
  // 4、释放资源 
  dis.close();
  client.close();

  server.close();
  }
 ​
 }
 ​
 /**
  * 熟悉流程
  * 创建客户端
  * 1、建立连接: 使用Socket创建客户端 +服务的地址和端口
  * 2、操作: 输入输出流操作
  * 3、释放资源 
  * @author 裴新 QQ:3401997271
  *
  */
 public class Client {
 ​
  public static void main(String[] args) throws UnknownHostException, IOException {
  System.out.println("-----Client-----");
  //1、建立连接: 使用Socket创建客户端 +服务的地址和端口
  Socket client =new Socket("localhost",8888);
  //2、操作: 输入输出流操作
  DataOutputStream dos =new DataOutputStream(client.getOutputStream());
  String data ="hello";
  dos.writeUTF(data);
  dos.flush();
  //3、释放资源 
  dos.close();
  client.close();
  }
 ​
 }
多用户交互
 /**
  * 模拟登录 多个客户端请求
  * 创建服务器
  * 1、指定端口 使用ServerSocket创建服务器
  * 2、阻塞式等待连接 accept
  * 3、操作: 输入输出流操作
  * 4、释放资源 
  * @author 裴新 QQ:3401997271
  *
  */
 public class LoginMultiServer {
  public static void main(String[] args) throws IOException {
  System.out.println("-----Server-----");
  // 1、指定端口 使用ServerSocket创建服务器
  ServerSocket server =new ServerSocket(8888);
  boolean isRunning =true;;
  // 2、阻塞式等待连接 accept
  while(isRunning) {
  Socket  client =server.accept(); 
  System.out.println("一个客户端建立了连接");
  new Thread(new Channel(client)).start();
  }
  server.close();
  }
  //一个channel就代表一个客户端
  static class Channel implements Runnable{
  private Socket  client;
  //输入流
  private DataInputStream dis;
  //输出流
  private DataOutputStream dos;
  public Channel(Socket  client) {
  this.client = client;
  try {
  //输入
  dis = new DataInputStream(client.getInputStream());
  //输出
  dos =new DataOutputStream(client.getOutputStream()); 
  } catch (IOException e) {
  e.printStackTrace();
  release();
  }

  }

  //接收数据
  private String receive() {
  String datas ="";
  try {
  datas = dis.readUTF();
  } catch (IOException e) {
  e.printStackTrace();
  }
  return datas;
  }
  //释放资源
  private void release() {
  // 4、释放资源 
  try {
  if(null != dos) {
  dos.close(); 
  }
  } catch (IOException e) {
  e.printStackTrace();
  }
  try {
  if(null != dis) {
  dis.close();
  }
  } catch (IOException e) {
  e.printStackTrace();
  }
  try {
  if(null != client) {
  client.close();
  }
  } catch (IOException e) {
  e.printStackTrace();
  }
  }
  //发送数据
  private void send(String msg) {
  try {
  dos.writeUTF(msg);
  dos.flush();
  } catch (IOException e) {
  e.printStackTrace();
  }
  }
  @Override
  public void run() { 
  // 3、操作: 输入输出流操作 
  String uname ="";
  String upwd ="";
  //分析
  String[] dataArray = receive().split("&");
  for(String info:dataArray) {
  String[] userInfo =info.split("=");
  if(userInfo[0].equals("uname")) {
  System.out.println("你的用户名为:"+userInfo[1]);
  uname = userInfo[1];
  }else if(userInfo[0].equals("upwd")) {
  System.out.println("你的密码为:"+userInfo[1]);
  upwd = userInfo[1];
  } 
  } 
  if(uname.equals("shsxt") && upwd.equals("laopei")) { //成功
  send("登录成功,欢迎回来");
  }else { //失败
  send("用户名或密码错误");
  }

  release();

  }

  }

 }
 /////////
 /**
  * 模拟登录  多个客户端请求
  * 创建客户端
  * 1、建立连接: 使用Socket创建客户端 +服务的地址和端口
  * 2、操作: 输入输出流操作
  * 3、释放资源 
  * @author 裴新 QQ:3401997271
  *
  */
 public class LoginMultiClient {
  public static void main(String[] args) throws UnknownHostException, IOException { 
  System.out.println("-----Client-----");
  //1、建立连接: 使用Socket创建客户端 +服务的地址和端口
  Socket client =new Socket("localhost",8888);
  //2、操作: 输入输出流操作  先请求后响应
  new Send(client).send();
  new Receive(client).receive(); 
  client.close();
  }
  //发送
  static class Send{
  private Socket client;
  private DataOutputStream dos;
  private BufferedReader console ;
  private String msg;
  public Send(Socket client) { 
  console=new BufferedReader(new InputStreamReader(System.in));
  this.msg =init();
  this.client = client;
  try {
  dos=new DataOutputStream(client.getOutputStream());
  } catch (IOException e) {
  e.printStackTrace();
  }
  }
  private String init() { 
  try {
  System.out.print("请输入用户名:");
  String uname =console.readLine();
  System.out.print("请输入密码:");
  String upwd =console.readLine();
  return "uname="+uname+"&"+"upwd="+upwd;
  } catch (IOException e) {
  e.printStackTrace();
  }
  return ""; 
  }

  public void send() {
  try {
  dos.writeUTF(msg);
  dos.flush();
  } catch (IOException e) {
  e.printStackTrace();
  }
  }
  }
  //接收
  static class Receive{
  private Socket client;
  private DataInputStream dis;
  public Receive(Socket client) {
  this.client = client;
  try {
  dis=new DataInputStream(client.getInputStream());
  } catch (IOException e) {
  e.printStackTrace();
  }
  } 
  public void receive() {
  String result;
  try {
  result = dis.readUTF();
  System.out.println(result);
  } catch (IOException e) {
  e.printStackTrace();
  } 

  }
  }
 }
 ​

相关文章

网友评论

    本文标题:第十六章 网络编程

    本文链接:https://www.haomeiwen.com/subject/zqizwctx.html