Java学习--网络编程知识

一、网络编程概述
计算机网络之间以何种规则进行通信,就是网络模型研究问题。
网络模型一般是指OSI(Open System Interconnection开放系统互连)七层参考模型,TCP/IP四层参考模型
主机至网络层(物理层 , 数据链路层) , 网际层 , 传输层 , 应用层(应用层 , 表示层 , 会话层)
二、协议
1.TCP/IP协议
Tcp是指传输控制协议
Ip是指网络地址协议
TCP/IP协议族按层次分别分为以下四层:应用层、传输层、网络层和数据链路层。
应用层
应用层决定了向用户提供应用服务时通信的活动
FTP(文件传输协议)、 http( 超文本传输协议)、 ssh(远程登录)、telnet (远程登录)DNS(域名系统)都属于该层
传输层
传输层对上层应用层提供处于网络连接中两台计算机之间的数据传输。
TCP(保障数据的可靠有序), UDP( 不保证数据可靠性)都属于传输层
网络层
网络层用于处理网络上流动的数据包。该层规定了通过怎样的路径到达对方的计算机,并把数据传送给对方。
ip协议属于网络层
链路层
链路层用来处理连接网络的硬件部分
2.HTTP协议
HTTP协议是位于应用层的协议。
2.1)请求
请求方式 资源地址 协议版本
请求首部字段(包括主机端口号)
例如:
GET /index.html HTTP/1.1
Host: localhost
2.2)响应
协议版本 状态码 状态码的原因短语
响应首部字段
三、使用telnet客户端程序
a.进入控制面板,在“程序”里找到“打开或关闭Windous功能”里找到telnet客户端并打勾
b.打开cmd命令窗口
c.与服务器端建立连接
输入:telnet 对方ip 端口号(80)
d.以http协议发送请求
发送完成后需要两个回车
e.接受返回结果

四、客户端编程
1.Socket编程
a创建Scoket
Socket socket = new Socket(“ip地址”, 端口号);
b发数据
socket.getOutputStream();
c收数据
socket.getInputStream();
编写一个简单的客户端程序,从客户端以http形式发送请求,在接受数据

public class testSocket {
    public static void main(String[] args) throws IOException {
    	//1.创建Scoket
        Socket socket = new Socket("localhost", 4396);
        OutputStream out = socket.getOutputStream();
        InputStream in = socket.getInputStream();
        //2.发数据
        out.write("GET /index.html HTTP/1.1\n".getBytes());
        out.write("Host: localhost\n".getBytes());
        out.write("\n\n".getBytes());
        3.收数据
        byte[] bt = new byte[1024 * 8];
        while(true){
            int l =in.read(bt);
            System.out.println(new String(bt, 0, l));
        }
        socket.close();
    }
}

2.URL编程
a建立连接并发送请求
HttpURLConnection connection = (HttpURLConnection)new URL(“http:主机地址:端口号/资源地址”).openConnection();
b接受数据
InputStream in = connection.getInputStream();
示例:从服务器端拿到一张图片并保存到本地。

public class TestURL {
    public static void main(String[] args) throws IOException {
        // 127.0.0.1 <==> localhost
        HttpURLConnection connection = (HttpURLConnection)new URL("http://192.168.3.123:80/img/chrome.png").openConnection();
   
        InputStream in = connection.getInputStream();
        FileOutputStream image = new FileOutputStream("e:\\2.png");
        while(true) {
            byte[] buf = new byte[1024*8];
            int len = in.read(buf);
            if(len == -1) {
                break;
            }
            image.write(buf, 0, len);
        }
        image.close();
        connection.disconnect();
    }
}

五、服务器端编程
a.一次只能响应一个客户端的程序:

public class testSeverSocket {
    public static void main(String[] args) throws IOException {
    	//1.创建serverSocket
        ServerSocket serverSocket = new ServerSocket(4396);
		//2.调用accept 等待客户端连接
        Socket accept = serverSocket.accept();
        InputStream in = accept.getInputStream();
        OutputStream out = accept.getOutputStream();
        byte[] bt = new byte[1024*8];
        while(true){
        //3.接收客户的输入
            int  len=in.read(bt);
            if(len==-1)
                break;
            //4. 拿到输出流向客户写入
            out.write(bt,0,len);
        }
    }
}

b.通过多线程,为每一个客户端程序都创建一个线程去处理。

public class ThreadServerSocket {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(4396);
        while(true){
            Socket accept = serverSocket.accept();
            new Thread(()->{
                try {
                    control(accept);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }

    private static void control(Socket accept) throws IOException {
        InputStream in = accept.getInputStream();
        OutputStream out = accept.getOutputStream();
        byte[] bt = new byte[1024*8];
        while(true){
           int  len=in.read(bt);
            if(len==-1)
                break;
            out.write(bt,0,len);
        }
    }
}

c.线程池
ExecutorService service = new ThreadPoolExecutor(,corePoolSize maxPoolSize, keepAliveTime , timeUnit, TimeUnit.SECONDS,BlockingQueue);
(1)corePoolSize 核心线程数。
(2)maxPoolSize 最大线程数 核心线程数+救急线程数<=最大线程数。
(3)keepAliveTime 保持时间 如果一个线程闲暇的时间超过了保持时间,那就把它回收,但不会少于核心线程数。
(4)timeUnit 时间单位。
(5)BlockingQueue 阻塞队列 当任务数超过核心线程数后,就把任务放入阻塞队列排队运行 (有界,无界)。

public static void main(String[] args) throws IOException {
        // 1. 创建serverSocket
        ServerSocket serverSocket = new ServerSocket(5000);
        System.out.println("服务已启动,等待连接");
        ExecutorService service = new ThreadPoolExecutor(10, 10, 0, TimeUnit.SECONDS,new LinkedBlockingQueue<>());

        while(true) {
            Socket socket = serverSocket.accept();
            System.out.println("客户端已连接....");
            service.submit(() -> {
                try {
                    handle(socket);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            });
        }
    }
    private static void handle(Socket socket) throws IOException {
        InputStream in = socket.getInputStream();
        OutputStream out = socket.getOutputStream();
        while (true) {
            byte[] buf = new byte[1024];
            int len = in.read(buf);
            if (len == -1) {
                break;
            }
            String echo = new String(buf, 0, len, "utf-8");
            System.out.println(echo);
            out.write(("服务器回答:" + echo).getBytes("utf-8"));
        }
    }
}

猜你喜欢

转载自blog.csdn.net/lyf_0922/article/details/84618893