【高编 2】 北邮 高级网络程序设计 2.Socket&HTTP

Socket, HTTP&HTML

导包

import java.net.*;
import java.io.*;

Get IP

InetAddress inetAddress = InetAddress.getByName(null);
InetAddress inetAddress = InetAddress.getByName("localhost");
InetAddress inetAddress = InetAddress.getByName("127.0.0.1");

Define Socket

Socket socket = new Socket(InetAddress.getByName(null), 8080);
ServerSocket serverSocket = new ServerSocket(8080);

Input

BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

Output

PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream)), true);

Sockets

IO流

a Socket is an abstraction of a network interface

Socket API 可用来:

  • Send data (bytes)
  • Receive data (bytes)
基本概念

流 —— 连接数据或将数据连接到目的地,是一连的字节流

  • input: 读入数据

  • output:发送数据/写入数据

流可以用来写入任何类型的数据

打开流后要记得关闭

∵A stream is an expensive resource, and there is a limit on the number of streams that you can have open at one time. You should not have more than one stream open on the same file

Java的两种流

byte stream

  • InputStream
  • OutputStream
  • 高效率

character stream

  • Reader
  • Writer
  • 需要翻译器
image-20211012130058601 image-20211012130107428

Socket

基本概念

网络接口的抽象概念,通过Socket API (Application Programming interface) 创建与远程电脑的相连,实现传输数据和接收数据

使用时需要导包:import java.net.*;

需要学会如何写远程机上的文件

Socket是流
  • 依靠流操作进行Socket的操作
  • Java可以一次处理多个连接,多线程
接收消息缓存器

BufferedReader

BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));

利用br.readLine()接收消息,返回值为 String

发送消息

PrintWriter

PrintWriter printWriter = new PrintWriter(new BufferedWriter(new OutputStreamWriter(myClient.getOutputStream())), true);

利用printWriter.println()来发送消息,参数可以是String也可以是int

MyClient

TCP发送消息

import java.net.*;
import java.io.*;

public class MyClient {
    public static void main(String[] args) throws IOException{
        Socket myClient = new Socket(InetAddress.getByName(null),8080);
        System.out.println("Addr=" + InetAddress.getByName(null));

        try{
            System.out.println("Socket = " + myClient);
            PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(myClient.getOutputStream())), true);
            BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            for(int i = 0; i < 10; i++){
                out.println("howdy " + i);
                String str = in.readLine();
                System.out.println(str);
            }
            out.println("END");
        } finally {
            myClient.close();
        }
    }
}
Server

TCP接收消息

import java.net.*;
import java.io.*;

public class MyServer {
    public static void main(String[] args) throws IOException{
        ServerSocket serverSocket = new ServerSocket(8080);
        Socket socket = serverSocket.accept();
		System.out.println("Started:" + serverSocket);
        try{
            BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
            while (true) {
                String str = br.readLine();
                if(str.equals("END")) break;
                System.out.println((char)Integer.parseInt(str));
                out.println(str);
            }
        } finally {
            socket.close();
            serverSocket.close();
        }
    }
}
多线程Socket
ServeOne
import java.net.*;
import java.io.*;

public class ServeOne extends Thread{
    private Socket socket;
    private BufferedReader in;
    private PrintWriter out;
    
    public ServeOne(Socket socket) throws IOException{
        this.socket = socket;
        in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), ture);
        start();
    }
    
    public void run(){
        try{
            
        } catch(IOException e){ System.err.println("IO Excpetion");}
        finally{
            try { socket.close(); }
            catch (IOException) { System.err.println("Socket not closed"); }
        }
    }
}
MultiServer
public class MultiServer{
    static final int PORT = 8080;
    public static void main(String[] args){
        ServerSocket serverSocket = new ServerSocket(PORT);
        System.out.println("Server started");
        try{
            while(true){
                Socket socket = s.accpet();
                try{
                    new ServerOne(socket);
                } catch (IOExcpetion){ socket.close(); }
                finally{
                    serverSocket.close();
                }
            }
        }
    }
}
ClientThread
import java.net.*;
import java.io.*;

public class ClientThread extends Thread{
    private Socket socket;
    private BufferedReader in;
    private PrintWriter out;
    private static int counter = 0;
    private int id = couter++;
    private static int threadCount = 0;
    
    public static int ThreadCount(){
        return threadCount;
    }
    
    public ClientThread(InetAddress addr){
        System.out.println("Making client" + id);
        threadCout++;
        
        try{
        	socket = new Socket(addr, MultServer.PORT);
        } catch (IOException e){
            System.err.prinln("Socket Failed");
        }
        
        try{
            in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
            start();
        } catch(IOExcpetion e){
            try{
                socket.close();
            } catch(IOEcpetion e2){ System.err.println("Socket not closed"); }
        }
    }
    
    public void run(){
        try{
            for (int i = 0; i < 5; i++){
                out.println("Client " + id + ": " + i);
                String str = in.readLine();
                System.out.println(str);
            }
            out.println("END");
        } catch (IOException e){
            System.err.println("IOExcpetion")
        } finally{
            try{
                socket.close();
            } catch (IOException e){
                System.err.println("Socket not closed");
            }
            threadCount--;
        }
    }
}
MultiClient
public class MultiClient{
	static final in MAX_THREAD = 40;
    public static void main(String[] args) throws IOExcpetion, InterruptedExcption{
        InetAddress addr = InetAddress.getByName(null);
        while(true){
            if (ClientThread.ThreadCount() < MAX_THREAD){
                new ClientThread(addr);
            }
            Thread.currentThread.sleep(100);
        }
    }
}

IP

每一台电脑都有一个 Unique Identifier —— IP,在网络上唯一标识机器:

  • 域名 Domain name
  • IP (Internet Protocol) address

127.0.0.1是本机的IP

每一个IP地址用32-bit number来表示

DNS

域名系统 Domain Name System

负责将域名与其IP地址相匹配

image-20211012130906237
本地域名解析

CMD 终端命令

nslookup www.eecs.qmul.ac.uk
Java中获取IP

导包:import java.net.*;

跑异常Exception

InetAddress 用来存储IP地址,并将其表示为域名或IP地址的形式

static InetAddress.getByName(String):存储域名String的IP地址

String getHostName():获取域名

String getHostAddress():获取IP地址

import java.net.*;
 
public class InetAddressTest {
	public static void main(String[] args) throws Exception {
 
		// 从来。
		InetAddress ia;
		ia = InetAddress.getLocalHost();// 获得本地主机的InetAddresss对象
		// 输出本地主机Ip地址
		System.out.println("本地主机IP地址:" + ia.getHostAddress());
		// 输出本地主机名
		System.out.println("本地主机名:" + ia.getHostName());
		// 输出本地主机ip地址
		System.out.println("本地主机Ip地址:" + ia.getHostAddress());
		// 获得百度网主机的InetAdderss 对象
		ia = InetAddress.getByName("www.baidu.com");// 获得主机名指定的InetAddress对象
		// 输出百度网主机IP地址
		System.out.println("百度网主机ip:" + ia.getHostAddress());
		// 输出百度网主机名
		System.out.println("百度网主机名:" + ia.getHostName());
 
	}
 
	private static InetAddress InetAddress(String string) {
		// TODO Auto-generated method stub
		return null;
	}
}
 

本地主机IP地址:27.18.219.15
本地主机名:2012-0101-0949
本地主机Ip地址:27.18.219.15
百度网主机ip:115.239.210.27
百度网主机名:www.baidu.com

服务器模型

Server:听取客户机的请求

Client:发送请求

image-20211012132159611
获取本机地址

Java 程序获取本地地址的对象

InetAddress addr = InetAddress.getByName(null);

InetAddress.getByName("localhost");

InetAddress.getByAddress("127.0.0.1");

端口

ip地址不足以去标识唯一的服务器(一个机器上可以有多个服务)上的每一个服务

Port:

  • 对机器上运行的service的特别标识符
  • 数值范围:0-65536

端口不是机器上的物理地址,而是软件的抽象

系统服务端口

端口: 0~1023

网络代理端口

8080

通常标识为IP地址:端口号形式

  • 127.0.0.1:8080
  • localhost:8080
常用端口

image-20211012132815649

HTTP

基本介绍

什么是HTTP

Hyper Text Transfer Protocol

什么是Web Page

一个URL包含了对象:HTML file,JPEG image

Server and Client

Server: Wait for request. Services requests and provides a response

Client: initiates a request

Browser & Server-side Program

Client (Browser): Send a request for the resource/document addressable by ONE URL

Server: 发送携带文件的response,或者检验用户发送内容的合法性

client-server模式的应用

在全部地方都有应用,许多协议都是为client-server模式服务的:RMI, HTTP, SMTP, TCP

HTTP

Context of HTTP

HTTP 是应用层的协议

依赖与其他层的协议来实现:TCP (Transport layer),IP(Network Layer),MAC(Datalink Layer)

OSI 模型
image-20211104135957498

HTTP and TCP

HTTP是建立在TCP上的

Socket socket = new Socket("10.0.0.1",80),利用80端口传输

TCP回顾

TCP = Transmission Control Protocol

Connection-Oriented

三次握手建立连接

四次分手断开连接

Reliable

Byte stream broken up into chunk called segments

image-20211104140222740

Detecting Error
image-20211104140244947

Byte Stream Service

TCP是利用字节流来传输数据的

TCP格式

每一个TCP segment有 20 bytes 的header以及data

image-20211104140343355
TCP port

系统应用使用 0~1023 端口

Web使用80端口

URL

Uniform Resource Locator

格式:

image-20211104140506901
filename#section

指向目录下的特定路径

  • 如果忽略,将指向index.html

Section属性值的是HTML文件中的named anchor,使用name属性来标记

<A name="123">...</A>

http://sunsite.unc.edu/javafaq/javafaq.html#abc123

其余使用URL的protocol
image-20211104140729401

HTTP协议Detail

HTTP指明了

  • 客户端和服务器如何建立连接
  • 客户端如何向服务器请求数据
  • 服务器如何回应请求
  • 如何关闭连接

stateless的协议:不记住任何从前的连接

Initiating a connection

HTTP/1.0, HTTP/1.1, HTTP/2.0 都是用TCP来建立连接的

浏览器和服务器都是使用 (TCP) socket 接口

  • 客户端写HTTP请求到Socket中并且读取socket中的http response
  • 服务端从Socket中读取HTTP请求并写response

连接的端口可以通过URL来指定

  • 如果没有指定,默认为80端口
HTTP step by step
  1. 发送TCP connection
  2. HTTP 客户端发送请求给服务器,请求中包含 path name
  3. HTTP 服务器从socket中接收到请求
    1. 从数据库中检索请求
    2. 封装object进入HTTP response message中
    3. 发送response给Client
  4. HTTP 服务器告诉TCP关闭连接
  5. 客户端接收到消息,关闭TCP连接
HTTP methods: GET and POST

两个HTTP请求方法:

GET
  • 请求URL中包含的查询字符串

  • 幂等:多个请求与单个请求具有相同的效果

  • 可缓存的

POST
  • 放置在 body of the HTTP request 中的查询字符串

  • 非幂等:POST两次就是两次

  • 当例如想要改变服务器端的数据时使用

GET的例子
image-20211104141928085
HTTP request message format
image-20211104143306890
HTTP response
image-20211104143343404
HTTP response message format
image-20211104143420581

Pipeline

从**HTTP 1.1才开始有**,允许一次HTTP连接中发送多次请求

HTTP method

image-20211104143613260

重要的Header

Cache-Control

  • Holds instructions for caching in requests and response

Etag

  • 对特定版本的资源的标识符

Vary

  • 允许定义是否为后续请求返回缓存的响应

Data

  • 显示被响应时的时间戳

Expires

  • 显示resouce被浏览时的时间戳

Pragma

  • 通常使用在解除Caching
More HTTP header

Content-Length:显示资源有多少字节

Content-Encoding:显示资源如何编码

Content-type:MIME type of object例如text/html

Set-Cookie header

Cookies包含了四个需要考虑部分

  • Response message中的cookie header line
  • Request message中的cookie header line
  • 用于保存用户的host信息,通常被browser保存
  • 网页背后的数据库
image-20211104144711468

HTTPS

HTTP Secure

  • TLS协议跑,不用TCP
  • Port 443

全部的payload(Header及Payload)都是encrypted

授权服务器

HTTPS URL

https://xxxxxx

HTTPs的问题

增加开销(overhead)

  • 只要必要时使用

增加了连接建立时间:

  • TCP setup + TLS handshake

增加了页面加载的时间

HTTP 2.0

目的减少页面加载时间

基于谷歌SPDY打造

  • 谷歌打造的,应用在谷歌的服务器上

Multiplexing

  • 不同的资源可以平行的request喝fetched,防止了head of line的blocking

Universal encryption

  • 全部默认为加密

Server push/hint

  • 服务器可以在收到request之前push resource
  • 可以提醒client fetch resources

Content prioritisation

  • 可以给resources赋优先度
  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

这不是Ourz的ID

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值