网络编程

1、概述

指的就是IO技术和网络技术的综合。

网络参考模型:OSI、TCP\IP参考模型

网络通讯要素:IP地址、端口号(用于标识进程的逻辑地址,不同进程的标识)、传输协议(通讯的规则)

package net.ip;

import java.net.InetAddress;
import java.net.UnknownHostException;

public class IPdemo {
    public static void main(String[] args) throws UnknownHostException {
        //ip地址对象 InetAddress
        //获取本地主机地址对象
        //没有构造方法,不能new对象
        //InetAddress ip = InetAddress.getLocalHost();

        //获取其他主机地址对象
        InetAddress ip = InetAddress.getByName("www.baidu.com");
        System.out.println(ip.getHostAddress()+":"+ip.getHostName());
    }
}

2、域名解析

3、端口

端口:物理端口

软件应用程序的数字表示:逻辑端口

4、传输协议TCP&UDP

传输控制协议、数据报文包协议

UDP(寄快递)、对讲机

1、面向无连接

2、不管对方在不在

3、包只能放64k的数据

4、速度快,不可靠

TCP(保证对方在)、打电话

1、面向有连接

2、三次握手

3、可靠,但是速度慢

5、网络编程Socket

socket:插座  IP+端口。

编写网络程序,先要有插座。针对不同的协议,有不同的插座。

in和out走的是管道。

6、UDP-发送端与接收端

通过查阅文档,了解到用于UDP传输协议的对象是DatagramSocket

通过UDP协议发送一段文本数据

1、先建立udp的socket,具备发送或者接收功能。

2、将数据封装到数据包中,数据包对象是DatagramPacket

3、使用socket对象的send方法,将数据包发送出去

4、关闭资源

package UDP;

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

public class UDP_send {
    public static void main(String[] args) throws IOException {
        System.out.println("udp发送端运行");
        //1、先建立udp的socket,具备发送或者接收功能。
        DatagramSocket ds = new DatagramSocket();
        //2、将数据封装到数据包中,数据包对象是DatagramPacket
        String text = "hello";
        byte[] buf = text.getBytes();
        DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("10.69.36.52"),10000);
        //3、使用socket对象的send方法,将数据包发送出去
        ds.send(dp);
        //4、关闭资源
        ds.close();
    }
}

接收端

1、现有udp 插座socket服务,接收端一定要明确端口,否则接收不到数据。

2、接收数据。之前,先将数据存储到数据包对象中,数据包对象才可以解析。

3、先定义数据包

4、通过数据包对象获取数据包中的各项内容。发送端IP、端口、数据等

5、关闭资源

package UDP;

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

public class UDP_receive {
    public static void main(String[] args) throws IOException {
        System.out.println("udp-receive");
        DatagramSocket ds = new DatagramSocket(10000); //如果不输入端口,则是随机分配端口
        byte[] buf = new byte[1024];
        DatagramPacket dp = new DatagramPacket(buf, buf.length);
        ds.receive(dp); //此方法在接收到数据包前一致阻塞
        String ip = dp.getAddress().getHostAddress();
        int port = dp.getPort();
        String text = new String(dp.getData(), 0, dp.getLength());
        System.out.println(text);
        ds.close();
    }
}

键盘录入

package UDP;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.*;

public class upd_send2 {
    public static void main(String[] args) throws IOException {
        System.out.println("发送端启动");
        DatagramSocket ds = new DatagramSocket();
        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
        String line = null;
        while ((line = bf.readLine()) != null) {
            if("over".equals(line)){
                break;
            }
            byte[] buf =line.getBytes();
            DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("10.69.36.52"),10000);
            ds.send(dp);
        }

        ds.close();
    }
}
package UDP;

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

public class udp_receive2 {
    public static void main(String[] args) throws IOException {
        System.out.println("接收端启动");
        DatagramSocket ds = new DatagramSocket(10000);
        while (true) {
            byte[] buf = new byte[1024];
            DatagramPacket dp = new DatagramPacket(buf, buf.length);
            ds.receive(dp); //此方法在接收到数据包前一致阻塞
            String ip = dp.getAddress().getHostAddress();
            int port = dp.getPort();
            String text = new String(dp.getData(), 0, dp.getLength());
            System.out.println("ip= "+ip+"  port = "+port+text);
        }
        //ds.close();
    }
}

在一个程序里面实现既能收,又能发

package UDP;

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

public class chatDemo {
    public static void main(String[] args) throws SocketException {
        //发送端的socket 接收端的socket
        DatagramSocket sendSocket = new DatagramSocket();
        DatagramSocket receiveSocket = new DatagramSocket(10002);
        send send = new send(sendSocket);
        receive receive = new receive(receiveSocket);
        //创建线程并开启
        Thread t1 = new Thread(send);
        Thread t2 = new Thread(receive);
        t1.start();
        t2.start();

    }
}
//发送任务
class send implements Runnable{
    private DatagramSocket ds;
    public send(DatagramSocket ds){
        super();
        this.ds = ds;
    }
    @Override
    public void run(){
        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
        String line = null;
        try {
            while ((line = bf.readLine()) != null) {
                byte[] buf =line.getBytes();
                DatagramPacket dp = new DatagramPacket(buf,buf.length, InetAddress.getByName("10.69.36.52"),10002);
                ds.send(dp);
                if ("over".equals(line)) {
                    break;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        ds.close();
    }
}
//接收任务
class receive implements Runnable{
    private DatagramSocket ds;
    public receive(DatagramSocket ds){
        super();
        this.ds = ds;
    }
    @Override
    public void run() {
        while (true) {
            byte[] buf = new byte[1024];
            DatagramPacket dp = new DatagramPacket(buf, buf.length);
            try {
                ds.receive(dp); //此方法在接收到数据包前一致阻塞
            } catch (IOException e) {
                e.printStackTrace();
            }
            String ip = dp.getAddress().getHostAddress();
            int port = dp.getPort();
            String text = new String(dp.getData(), 0, dp.getLength());
            System.out.println("ip= "+ip+"  port = "+port+text);
            if(text.equals("over")){
                System.out.println(ip+"....离开聊天室");
            }
        }
    }
}

使用广播的方法

发送的IP地址改为广播地址即可

7、TCP

TCP也分两端,一个叫客户端,一个叫服务端。

TCP客户端用的就是Socket对象。服务端用的是ServerSocket对象。

客户端运行

package TCP;

import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;

public class TCP_client {
    public static void main(String[] args) throws IOException {
        //需求:通过Tcp传输,将数据发送给服务器
        Socket socket = new Socket(InetAddress.getByName("DESKTOP-IG0R9HM").getHostAddress(),10003);//如果无参,则创建的是未连接的socket,所以要明确服务器端的地址和端口
        byte[] buf = new byte[1024];
        OutputStream os = socket.getOutputStream();
        os.write("你好,tcp".getBytes());
        socket.close();
    }
}

服务器端

package TCP;

import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class TCP_Server {
    public static void main(String[] args) throws IOException {
        ServerSocket ss = new ServerSocket(10003);
        Socket s = ss.accept();
        InputStream is = s.getInputStream();
        byte[] buf = new byte[1024];
        int len = is.read(buf);
        String text = new String(buf,0,len);
        System.out.println(text);
        System.out.println("客户端地址是:"+s.getInetAddress().getHostAddress());
        s.close();
        ss.close();
    }
}

tcp在传输过程中,两端都有可能处于等待状态。

并发访问的时候,出的问题。

第一个客户端如果连接,没有发数据,或者发完没有结束,那么accept方法会处于阻塞状态。

package TCP;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class TCP_server2 {
    public static void main(String[] args) throws IOException {
        ServerSocket ss = new ServerSocket(10004);
        Socket s = ss.accept();

        InputStream ip = s.getInputStream();
        byte[] buf = new byte[1024];
        int len = ip.read(buf);
        String reveive = new String(buf, 0, len);
        System.out.println(reveive);

        OutputStream op = s.getOutputStream();
        op.write("这里是服务器端".getBytes());
        System.out.println(s.getInetAddress().getHostAddress()+"已连接");
        s.close();
//      ss.close(); 如果不断获取客户端,则不用关服务器
    }
}
package TCP;

import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;

public class TCP_client2 {
    public static void main(String[] args) throws IOException {
        Socket s = new Socket(InetAddress.getByName("DESKTOP-IG0R9HM").getHostAddress(), 10004);
        OutputStream op = s.getOutputStream();
        op.write("这里是客户端".getBytes());

        InputStream is = s.getInputStream();
        byte[] buf = new byte[1024];
        int len = is.read(buf);
        String reveive = new String(buf,0,len);
        System.out.println(reveive);

        s.close();

    }
}

8、频繁的客户端和服务端的通信

需求:客户端通过键盘录入发送数据到服务端,服务端将接受的数据显示到屏幕上的同时,将这些数据转成大写发回给客户端。当客户端录入的是over时,结束。

客户端:

1、创建Socket,明确地址和端口。

2、源:键盘录入,获取需要转换的数据 。

3、目的:socket输出流。

4、源:socket  读取流,读取客户端发回来的大写数据

5、目的:客户端显示器,将大写数据显示出来。

6、频繁的读写操作

7、关闭资源

package TCP;

import java.io.*;
import java.net.InetAddress;
import java.net.Socket;

public class client_uplow {
    public static void main(String[] args) throws IOException {
        System.out.println("客户端运行");
        //1、创建Socket,明确地址和端口。
        Socket s = new Socket(InetAddress.getByName("DESKTOP-IG0R9HM").getHostAddress(),10004);
        //2、源:键盘录入,获取需要转换的数据 。
        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
        //3、目的:socket输出流。
        OutputStream op = s.getOutputStream();
        //都是字符数据,为了便于操作,使用额外功能,转换,同时提高效率。
        //BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(op));
        //也可以使用打印流
        PrintWriter pw = new PrintWriter(s.getOutputStream());
        //4、源:socket  读取流,读取客户端发回来的大写数据
        //InputStream is = s.getInputStream();
        BufferedReader bufr = new BufferedReader(new InputStreamReader(s.getInputStream()));
        //5、目的:客户端显示器,将大写数据显示出来。
        String receiver = null;
        while ((receiver = bf.readLine())!= null){
            //将读取键盘的数据发送到服务端
            pw.println(receiver);
            pw.flush();
            //读取服务端返回的数据
            String up = bufr.readLine();
            System.out.println(up);
            if("over".equals(receiver)){
                break;
            }
        }
        //7、关闭资源
        s.close();
    }
}

服务端:

1、创建服务端socket,监听一个端口。

2、源:socket输入流,读取客户端数据。

3、将数据转换成大写

4、目的:socket输出流,发送给客户端数据。

5、频繁的读写操作

6、关闭资源

package TCP;

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

public class Server_uplow {
    public static void main(String[] args) throws IOException {
        System.out.println("服务端运行");
       // 1、创建服务端socket,监听一个端口。
        ServerSocket ss = new ServerSocket(10004);
        while (true){
         Socket s = ss.accept();
            System.out.println(s.getInetAddress().getHostAddress()+"...已连接");
         // 2、源:socket输入流,读取客户端数据。
        BufferedReader brIn = new BufferedReader(new InputStreamReader(s.getInputStream()));
        //3、将数据转换成大写
        PrintWriter out = new PrintWriter(s.getOutputStream());
       // 4、目的:socket输出流,发送给客户端数据。
        String line = null;
        while ((line = brIn.readLine())!= null){
            if("over".equals(line)){
                break;
            }
            System.out.println(line);
            //将读取到的字母数据转成大写
            out.println(line.toUpperCase());
            out.flush();
        }
       // 5、频繁的读写操作
       // 6、关闭资源
        s.close();
         }
    }
}

9、上传文本文件

客户端

package TCP;

import java.io.*;
import java.net.InetAddress;
import java.net.Socket;

public class upload_client {
    public static void main(String[] args) throws IOException {
        System.out.println("客户端运行");
        Socket s = new Socket(InetAddress.getByName("DESKTOP-IG0R9HM"), 10008);

        //读取文本文件
        BufferedReader bf_read = new BufferedReader(new FileReader("F:\\javatest\\list.txt"));

        PrintWriter out = new PrintWriter(s.getOutputStream());

        BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));

        String line = null;
        while ((line = bf_read.readLine())!= null){
            out.println(line);
            out.flush();

            String re = bufIn.readLine();
            System.out.println(re);
        }
        out.println("over");
        System.out.println("发送over成功");
        s.close();
    }
}

服务器端

package TCP;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class upload_server {
    public static void main(String[] args) throws IOException {
        System.out.println("服务端启动");
        ServerSocket ss = new ServerSocket(10008);
        Socket s = ss.accept();
        //获得服务器端的读取流
        BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
        //获取服务器端的输出流
        PrintWriter pw = new PrintWriter(s.getOutputStream());
        BufferedWriter bw = new BufferedWriter(new FileWriter("F:\\javatest\\tempfile\\receive.txt"));

        String line = null;
        while ((line = br.readLine())!= null){
            if("over".equals(line)){
                break;
            }
            System.out.println(line);
            pw.println(line);
            bw.write(line);
            bw.newLine();
            pw.flush();
            bw.flush();
        }
        bw.close();
        s.close();
        ss.close();

    }
}

这里说一下碰到的问题

在服务器端的程序里面。在频繁读取的过程中,只考虑到了pw.println,但是没有考虑到,pw获取的是socket的输出流,并不是文件的输出流,写入的过程还需要bw来进行写入。所以碰到的问题就是,客户端已经发送完毕,服务器端也接收到了,但是就是没有写入到文件中。

字符流能不能复制媒体文件

不能,每次读取字节都需要查表,有的查表查不到,编码表会将查不到的就用未知的字符(固定的)替代。所以传输过去就会出现问题。所以复制图片,部分是有问题的。

10、上传图片-客户端

服务器端:

package TCP;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class pic_upload_Server {
    public static void main(String[] args) throws IOException {
        System.out.println("服务端运行");
        ServerSocket ss = new ServerSocket(10007);
        //获取客户端
        while (true) {
            Socket s = ss.accept();
            System.out.println(s.getInetAddress().getHostAddress() + "...已连接");
            //读取图片数据
            InputStream isIn = s.getInputStream();
            //写数据
            FileOutputStream fos = new FileOutputStream("F:\\javatest\\2.jpg");
            byte[] buf = new byte[1024];
            int len = 0;
            while ((len = isIn.read(buf)) != -1) {
                fos.write(buf, 0, len);
            }

            //给客户端一个回复信息
            OutputStream os = s.getOutputStream();
            os.write("上传成功".getBytes());
            fos.close();
            s.close();
        }
    }
}

客户端:

package TCP;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;

public class pic_upload_client {
    public static void main(String[] args) throws IOException {
        System.out.println("客户端运行");
        //1、创建socket
        Socket s = new Socket(InetAddress.getByName("DESKTOP-IG0R9HM"), 10007);
        //2、读取源图片
        FileInputStream fis = new FileInputStream("F:\\javatest\\1.jpg");
        //3、目的
        OutputStream os = s.getOutputStream();
        //4、读写操作
        byte[] buf = new byte[1024];
        int len = 0;
        while ((len = fis.read(buf)) != -1) {
            os.write(buf,0,len);
        }
        //告诉服务器端图片数据发送完毕
        s.shutdownOutput();
        //读取上传成功字样
        InputStream in = s.getInputStream();
        byte[] bufin = new byte[1024];
        int lenin = in.read(bufin);
        System.out.println(new String(bufin,0,lenin));
        fis.close();
        s.close();
    }
}

注意一个函数

s.shutdownOutput();

注意一个问题:如果服务器没有关,再上传一次,那么就会出现图片的重名的问题。

有一个编号很常见,那就是你上传的时间,这个基本不会产生冲突。

或者命名为用户的IP。

package TCP;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class pic_upload_Server {
    public static void main(String[] args) throws IOException {
        System.out.println("服务端运行");
        ServerSocket ss = new ServerSocket(10007);
        //获取客户端
        while (true) {
            Socket s = ss.accept();
            String ip = s.getInetAddress().getHostAddress();
            System.out.println(ip + "...已连接");
            //读取图片数据
            InputStream isIn = s.getInputStream();
            //写数据
            File dir = new File("F:\\javatest\\mypic");
            if (!dir.exists()) {
                dir.mkdir();
            }
            File pic = new File(dir, ip + ".jpg");
            FileOutputStream fos = new FileOutputStream(pic);
            byte[] buf = new byte[1024];
            int len = 0;
            while ((len = isIn.read(buf)) != -1) {
                fos.write(buf, 0, len);
            }

            //给客户端一个回复信息
            OutputStream os = s.getOutputStream();
            os.write("上传成功".getBytes());
            fos.close();
            s.close();
        }
    }
}

或者使用下面的方式:

package TCP;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class pic_upload_Server {
    public static void main(String[] args) throws IOException {
        System.out.println("服务端运行");
        ServerSocket ss = new ServerSocket(10007);
        //获取客户端
        while (true) {
            Socket s = ss.accept();
            String ip = s.getInetAddress().getHostAddress();
            System.out.println(ip + "...已连接");
            //读取图片数据
            InputStream isIn = s.getInputStream();
            //写数据
            File dir = new File("F:\\javatest\\mypic");
            if (!dir.exists()) {
                dir.mkdir();
            }
            //为了避免覆盖,通过给重名的文件进行编号。
            int count = 1;
            File pic = new File(dir, ip + "(" + count + ")" + ".jpg");
            if (pic.exists()) {
                count++;
                pic = new File(dir,ip + "(" + count + ")" + ".jpg");
            }
            FileOutputStream fos = new FileOutputStream(pic);
            byte[] buf = new byte[1024];
            int len = 0;
            while ((len = isIn.read(buf)) != -1) {
                fos.write(buf, 0, len);
            }

            //给客户端一个回复信息
            OutputStream os = s.getOutputStream();
            os.write("上传成功".getBytes());
            fos.close();
            s.close();
        }
    }
}

有一个问题就是

客户端多次上传,但是后面的并没有存储。问题出在if上,只是判断了一次。所以应该改成while,只要存在就++。

package TCP;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class pic_upload_Server {
    public static void main(String[] args) throws IOException {
        System.out.println("服务端运行");
        ServerSocket ss = new ServerSocket(10007);
        //获取客户端
        while (true) {
            Socket s = ss.accept();
            String ip = s.getInetAddress().getHostAddress();
            System.out.println(ip + "...已连接");
            //读取图片数据
            InputStream isIn = s.getInputStream();
            //写数据
            File dir = new File("F:\\javatest\\mypic");
            if (!dir.exists()) {
                dir.mkdir();
            }
            //为了避免覆盖,通过给重名的文件进行编号。
            int count = 1;
            File pic = new File(dir, ip + "(" + count + ")" + ".jpg");
            while (pic.exists()) {
                count++;
                pic = new File(dir,ip + "(" + count + ")" + ".jpg");
            }
            FileOutputStream fos = new FileOutputStream(pic);
            byte[] buf = new byte[1024];
            int len = 0;
            while ((len = isIn.read(buf)) != -1) {
                fos.write(buf, 0, len);
            }

            //给客户端一个回复信息
            OutputStream os = s.getOutputStream();
            os.write("上传成功".getBytes());
            fos.close();
            s.close();
        }
    }
}

还有一个问题:并发上传的问题

通过多线程来解决

每个客户端都需要单独一个线程来处理

package TCP;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class pic_upload_Server {
    public static void main(String[] args) throws IOException {
        System.out.println("服务端运行");
        ServerSocket ss = new ServerSocket(10007);
        //获取客户端
        while (true) {
            Socket s = ss.accept();
            //要想实现多个客户端并发上传,服务器端必须启动多个线程来完成。
            new Thread(new uploadpic(s)).start();  //新线程,线程里面得有任务,任务里面得有客户端。
            //new Thread(new 类的对象).start   对应的类里面应该有重写run方法。
            
        }
    }
}
package TCP;

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

public class uploadpic implements Runnable {
    private Socket s;
    public uploadpic(Socket s) {
        this.s = s;
    }
    public void run(){
        try{
            String ip = s.getInetAddress().getHostAddress();
            System.out.println(ip + "...已连接");
            //读取图片数据
            InputStream isIn = s.getInputStream();
            //写数据
            File dir = new File("F:\\javatest\\mypic");
            if (!dir.exists()) {
                dir.mkdir();
            }
            //为了避免覆盖,通过给重名的文件进行编号。
            int count = 1;
            File pic = new File(dir, ip + "(" + count + ")" + ".jpg");
            while (pic.exists()) {
                count++;
                pic = new File(dir,ip + "(" + count + ")" + ".jpg");
            }
            FileOutputStream fos = new FileOutputStream(pic);
            byte[] buf = new byte[1024];
            int len = 0;
            while ((len = isIn.read(buf)) != -1) {
                fos.write(buf, 0, len);
            }

            //给客户端一个回复信息
            OutputStream os = s.getOutputStream();
            os.write("上传成功".getBytes());
            fos.close();
            s.close();
        }catch (IOException e){
            e.printStackTrace();
        }
    }
}

11、常见的客户端和服务端原理(浏览器、tomcat)

客户端

浏览器、QQ等。

服务端

Tomcat服务器:对外提供web资源的服务。默认端口为8080.

服务器:对外提供服务的机器。

底层所使用的网络传输通讯机制

访问方式:浏览器中:输入http://主机地址:8080/自己的应用程序名称/具体的资源名称;

12、浏览器发送的HTTP请求消息

了解浏览器都做了什么事情?

客户端:浏览器

服务端:自定义的服务端myServer

package HTTP;

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

public class myServer {
    public static void main(String[] args) throws IOException {
       //自定义server服务端,获取浏览器的信息。并反馈信息。
        System.out.println("服务端启动");
        ServerSocket ss = new ServerSocket(9090);
        Socket s = ss.accept();
        System.out.println(s.getInetAddress().getHostAddress()+"...已连接。");
        InputStream is = s.getInputStream();
        byte[] buf = new byte[1024];
        int len = is.read(buf);
        String text = new String(buf, 0, len);
        System.out.println(text);
        //回馈数据
        PrintWriter pw = new PrintWriter(s.getOutputStream(), true);
        pw.println("<font color = 'red' size = 7>欢迎访问</font>");
        s.close();
        ss.close();
    }
}

在浏览器界面输入本地地址:9090,就可以看到服务器返回的欢迎访问消息。并且服务器端会收到来自浏览器的http请求消息

GET / HTTP/1.1    //请求行 访问资源的路径 HTTP协议版本
//属性信息,通过键值对来表示
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36 Edge/17.17134
Accept-Language: zh-CN
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Upgrade-Insecure-Requests: 1
Accept-Encoding: gzip, deflate
Host: 10.69.36.52:9090
Connection: Keep-Alive
空行
请求体

HTTP的请求消息:请求头+请求体,中间有空行(专门区分头和体的)。

13、模拟浏览器&HTTP的应答消息

package HTTP;

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.Socket;

public class browser {
    public static void main(String[] args) throws IOException {
      //模拟一个浏览器,发送之前IE发送的HTTP消息
        Socket s = new Socket("10.69.36.52",9090);
        //把IE的信息发送给服务端
        PrintWriter out = new PrintWriter(s.getOutputStream(),true);
        out.println("GET / HTTP/1.1");
        out.println("User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36 Edge/17.17134");
        out.println("Accept-Language: zh-CN");
        out.println("Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
        out.println("Upgrade-Insecure-Requests: 1");
        out.println("Accept-Encoding: gzip, deflate");
        out.println("Host: 10.69.36.52:9090");
        out.println("Connection: clsoe");
        out.println(); //空行
        //读取服务端的数据
        InputStream is = s.getInputStream();
        byte[] buf = new byte[1024];
        int len = is.read(buf);
        String text = new String(buf, 0, len);
        System.out.println(text);
        s.close();
    }
}

服务器如果是tomcat。则会收到tomcat服务器返回的数据

服务器端HTTP应答消息:

HTTP/1/1 200 OK  //应答行  http协议版本  应答状态码  
Server:Apache-Coyote/1.1
Accept-Ranges:bytes
Etag:W/"67-1374891778953"
Last-Modified:Sat,27 Jul 2013 02:22:34 GMT
Content-Type:text/html    //内容类型
Content-Length:467        //内容长度
Data:Sun,01.. 
Connection:close
空行
应答体

14、URL对象

类 URL

代表一个统一资源定位符。

package URL;

import java.net.MalformedURLException;
import java.net.URL;

public class urlDemo {
    public static void main(String[] args) throws MalformedURLException {
        String str_url = "http://10.69.36.52:9090/?name=liudong&age=25";
        //将URL地址封装成对象
        URL url = new URL(str_url);
        System.out.println("协议:" + url.getProtocol());
        System.out.println("主机:" + url.getHost());
        System.out.println("端口:"+url.getPort());
        System.out.println("路径:"+url.getPath());
        System.out.println("文件:"+url.getFile());
        System.out.println("getQuery:"+url.getQuery());
    }
}

URL有一个特殊的方法,openConnection();获取url的连接

该方法返回一个URLconnection对象,它表示到URL所引用的远程对象的连接。

都不用使用Socket对象了,因为已经封装。

package URL;

import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;

public class urlDemo {
    public static void main(String[] args) throws IOException {
        String str_url = "http://10.69.36.52:9090";
        //将URL地址封装成对象
        URL url = new URL(str_url);
/*        System.out.println("协议:" + url.getProtocol());
        System.out.println("主机:" + url.getHost());
        System.out.println("端口:"+url.getPort());
        System.out.println("路径:"+url.getPath());
        System.out.println("文件:"+url.getFile());
        System.out.println("getQuery:"+url.getQuery());*/
        //获取指定资源的连接对象   //封装了Socket
        URLConnection conn = url.openConnection();
//        System.out.println(conn);
        InputStream is = conn.getInputStream();
        byte[] buf = new byte[1024];
        int len = is.read(buf);
        String text = new String(buf, 0, len);
        System.out.println(text);

    }
}

15、HTTP1.0和HTTP1.1的区别

当我们访问有图片的网站时,它不止有一次请求。随后还会有对图片的请求。

http1.1就是传说中的keep-alive。

16、CS和BS

常见的网络架构:

C/S:client/server

特点:

1、程序员需要开发客户端和服务端

2、维护较为麻烦

3、将一部分运算转移到客户端来完成,减轻服务器端的压力

B/S:browser/server

特点:

1、程序员只需要开发服务端,客户端使用系统已有的浏览器即可

2、维护很简单,只需要维护服务端

3、所有的运算都在服务端

4、带宽问题和安全问题

目前流行B/S网络架构。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值