Java网络编程

http协议

HTTP协议的版本

  HTTP/1.0、HTTP/1.1
区别:
  1.0:每次响应后即刻关闭了连接。客户端与web服务器建立连接后,只能获得一个web资源。
  1.1:不是每次响应后挂断,等待长时间以后没有请求会挂断。允许客户端与web服务器建立连接后,在一个连接上获取多个web资源。

请求部分

请求行
  提交方式
    提交方式有很多,常用的GET和POST;
      GET和POST的区别:
        GET的提交的参数会显示到地址栏上,而POST不显示.
        GET往往是有大小限制的,而POST没有大小的限制.
        GET没有请求体,而POST有请求体.
  提交路径
  协议版本

请求头
  都是键值对的形式显示的.一般一个key对应一个value,也有个别的是一个key对应多个value。
  HTTP请求中的常用消息头:
  User-Agent:代表浏览器的类型。 --文件下载:下载中文文件,IE使用URLEncodor进行编码,而Firefox使用Base64编码。
  accept:浏览器通过这个头告诉服务器,它所支持的数据类型
  Accept-Charset: 浏览器通过这个头告诉服务器,它支持哪种字符集
  Accept-Encoding:浏览器通过这个头告诉服务器,支持的压缩格式
  Accept-Language:浏览器通过这个头告诉服务器,它的语言环境
  Host:浏览器通过这个头告诉服务器,想访问哪台主机
  If-Modified-Since: 浏览器通过这个头告诉服务器,缓存数据的时间
  Referer:浏览器通过这个头告诉服务器,客户机是哪个页面来的  防盗链
  Connection:浏览器通过这个头告诉服务器,请求完后是断开链接还是何持链接存

请求体
  就是POST提交方式的提交的参数

响应部分

响应行
  协议版本
  状态码:
    200  成功
    302  重定向
    304  查找本地缓存
    404  资源不存在
    500  服务器内部错误
  状态码描述

响应头:键值对,一般一个key对应一个value,也有一个key对应多个value。
  HTTP响应中的常用响应头(消息头)
  Location:服务器通过这个头,来告诉浏览器跳到哪里
  Server:服务器通过这个头,告诉浏览器服务器的型号
  Content-Encoding:服务器通过这个头,告诉浏览器,数据的压缩格式
  Content-Length: 服务器通过这个头,告诉浏览器回送数据的长度
  Content-Language: 服务器通过这个头,告诉浏览器语言环境
  Content-Type:服务器通过这个头,告诉浏览器回送数据的类型
  Refresh:服务器通过这个头,告诉浏览器定时刷新
  Content-Disposition: 服务器通过这个头,告诉浏览器以下载方式打数据
  Transfer-Encoding:服务器通过这个头,告诉浏览器数据是以分块方式回送的
  Expires: -1  控制浏览器不要缓存
  Cache-Control: no-cache  
  Pragma: no-cache

响应体:显示浏览器的页面的内容。

在服务端设置响应头来控制客户端浏览器的行为

设置Location响应头,实现请求重定向

response.setStatus(302);//设置服务器的响应状态码

response.setHeader("Location", "/demo5-refresh/success.html ");

设置content-type响应头,指定回送数据类型

String type = this.getServletContext().getMimeType(filename);

response.setHeader("Content-Type", type);

设置refresh响应头,让浏览器定时刷新

response.setHeader("refresh", "3;url='http://www.baidu.com'");

设置content-disposition响应头,让浏览器下载文件

response.setHeader("content-disposition", "attachment;filename=xxx.jpg");


网络编程

InetAdderss类,该类用于封装一个IP地址,并提供了一系列与IP地址相关的方法。

UDP 用户数据报协议

DatagramPacket类,该类的实例对象就相当于一个集装箱,用于封装UDP通信中发送或者接收的数据。

接收端的构造方法只需要接收一个字节数组来存放接收到的数据,而发送端的构造方法不但要接收存放了发送数据的字节数组,还需要指定发送端IP地址和端口号。

DatagramPacket(byte[] buf, int length)  构造 DatagramPacket,用来接收长度为 length 的数据包。
DatagramPacket(byte[] buf, int length, InetAddress address, int port)  构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。

DatagramSocket类的作用就类似于码头,使用这个类的实例对象就可以发送和接收DatagramPacket数据包。

在创建发送端和接收端的DatagramSocket对象时,使用的构造方法也有所不同。

DatagramSocket()  构造数据报套接字并将其绑定到本地主机上任何可用的端口。
DatagramSocket(int port)  创建数据报套接字并将其绑定到本地主机上的指定端口。

package com.boomoom;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;

/*
 * 使用UDP协议发送数据
 */
public class SendDemo {
    public static void main(String[] args) throws IOException  {
        //创建发送端Socket对象
        DatagramSocket ds = new DatagramSocket();

        //创建数据并打包        
        String s = "hello body, im a coder!";
        byte[] bys = s.getBytes();
        int length = bys.length;
        InetAddress address = InetAddress.getByName("boomoom");//发送给当前设备
        int port = 8888;
        DatagramPacket dp = new DatagramPacket(bys,length,address,port);
        ds.send(dp);
        ds.close();
    }
}


package com.boomoom;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

/*
 * 使用UDP协议接收数据
 */
public class ReceiveDemo {
    public static void main(String[] args) throws IOException {
        //创建接收端Socket对象
        DatagramSocket ds = new DatagramSocket(8888);
        //接收数据
        //DatagramPacket(byte[] buf, int length) 
        byte[] bys = new byte[1024];
        DatagramPacket dp = new DatagramPacket(bys,bys.length);
                
        System.out.println(1);
        ds.receive(dp);//阻塞
        System.out.println(2);
        
        //解析数据
        InetAddress address = dp.getAddress(); // 获取发送端的IP对象
        int length = dp.getLength();
        
        System.out.println("sender ---> " + address.getHostAddress());
        System.out.println(new String(bys,0,length));
        ds.close();
    }
}
使用UDP协议发送接收数据

TCP 传输控制协议

UDP 中只有发送端和接收端,不区分客户端与服务器端,计算机之间可以任意地发送数据。而 TCP 通信是严格区分客户端与服务器端的,在通信时,必须先由客户端去连接服务器端才能实现通信,服务器端不可以主动连接客户端,并且服务器端程序需要事先启动,等待客户端的连接。在 JDK 中提供了两个类用于实现 TCP 程序,一个是 ServerSocket 类,用于表示服务器端,一个是 Socket 类,用于表示客户端。

ServerSocket类,的实例对象可以实现一个服务器端的程序。

Socket类,用于实现TCP客户端程序。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

public class ClientTest {
    public static void main(String[] args) throws  IOException  {
        //创建客户端Socket对象
        Socket s = new Socket("janden-pc",8888);

        //获取用户名和密码
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        System.out.println("请输入用户名:");
        String username = br.readLine();
        System.out.println("请输入密码:");
        String password = br.readLine();


        //获取输出流对象
        PrintWriter out = new PrintWriter(s.getOutputStream(),true);
        //写出数据
        out.println(username);
        out.println(password);

        //获取输入流对象
        BufferedReader serverBr = new BufferedReader(new InputStreamReader(s.getInputStream()));
        //获取服务器返回的数据
        String result = serverBr.readLine();
        System.out.println(result);
        //释放资源
        s.close();
    }
}

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.List;

public class ServerTest {
    public static void main(String[] args) throws IOException {
        //创建服务器端Socket对象
        ServerSocket ss = new ServerSocket(8888);
        //监听
        Socket s = ss.accept();
        //获取输入流对象
        BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
        String username = br.readLine();
        String password = br.readLine();

        boolean flag = false;
        List<User> users = UserDB.getUsers();
        User user = new User(username,password);
        if(users.contains(user)) {
            flag = true;
        }

        //获取输出流对象
        PrintWriter out = new PrintWriter(s.getOutputStream(),true);

        //返回判断信息
        if(flag) {
            out.println("登陆成功");
        }
        else {
            out.println("登陆失败");
        }
        //释放资源
        s.close();
        //ss.close();//服务器一般不关闭
    }
}


import java.util.ArrayList;
import java.util.List;

public class UserDB {
    private static List<User> users = new ArrayList<User>();
    
    static {
        users.add(new User("张三","123"));
        users.add(new User("赵四","1234"));
        users.add(new User("阿Q","12345"));
        users.add(new User("尼古拉斯","123456")); 
    }

    public static List<User> getUsers() {
        return users;
    }
}

import java.util.Objects;

public class User {
    private String username;
    private String password;

    public User() {
        super();
    }

    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        User user = (User) o;
        return Objects.equals(username, user.username) &&
                Objects.equals(password, user.password);
    }
}
使用TCP协议收发数据

在应用层写入的数据经由表示层格式化编码,再由会话层标记发送顺序后才被发送出去。
会话层只对何时建立连接、何时发送数据等问题进行管理。
传输层建立连接或断开连接,创建逻辑上的通信连接。为保证数据传输的可靠性,它会在通信两端之间进行确认,并负责重发。
网络层将数据传输给对端。
数据链路层的作用是还在传输介质互联的设备间进行数据处理。
物理层将数据转为电压或脉冲光传输给物理的传输介质。

发一封邮件为例
应用层的首部 标明收件人邮件主题内容。
表示层的首部 编码格式识别信息。
会话层的首部 记录数据传送顺序。
传输层的首部 用以识别传输层。
网络层的首部 两端IP地址、协议等。
数据链路层的首部 帧定界符合长度上限。
物理层的首部 含有MAC地址。

原文地址:https://www.cnblogs.com/boomoom/p/10312184.html