复习(基础5)网络编程

 

1.网络编程三要素

实现网络编程关键的三要素

IP地址:设备在网络中的地址,是唯一的标识。

端口:应用程序在设备中唯一的标识。

协议:   数据在网络中传输的规则,常见的协议有UDP协议和TCP协议。

1.1、IP地址

IP(Internet Protocol):全称互联网协议地址,是分配给上网设备的唯一标志。

常见的IP分类为:IPv4IPv6

IPv4:

IPv6128位(16个字节),号称可以为地球每一粒沙子编号。

IPv6分成8个整数,每个整数用四个十六进制位表示, 数之间用冒号(:)分开。

 IP地址基本寻路

IP地址形式:

        公网地址、和私有地址(局域网使用)

        192.168. 开头的就是常见的局域网地址,范围即为192.168.0.0--192.168.255.255,专门为组织机构内部使用。

IP常用命令:

        ipconfig:查看本机IP地址

        ping IP地址:检查网络是否连通

特殊IP地址

        本机IP: 127.0.0.1或者localhost:称为回送地址也可称本地回环地址,只会寻找当前所在本机。

InetAddress 的使用

此类表示Internet协议(IP)地址。

名称

说明

public static InetAddress getLocalHost()

返回本主机的地址对象

public static InetAddress getByName​(String host)

得到指定主机的IP地址对象,参数是域名或者IP地址

public String getHostName​()

获取此IP地址的主机名

public String getHostAddress​()

返回IP地址字符串

public boolean isReachable(int timeout)

在指定毫秒内连通该IP地址对应的主机,连通返回true

package com.itwpf.d1_interAddress;

import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;

public class InterAddressDemo1 {
    public static void main(String[] args) throws IOException {
        //获取本机地址对象
        InetAddress ip1 = InetAddress.getLocalHost();
        System.out.println("本机名:"+ip1.getHostName());
        System.out.println("本机ip地址:"+ip1.getHostAddress());

        System.out.println("-------------------");

        //获取域名ip对象
        InetAddress ip2 = InetAddress.getByName("www.baidu.com");
        System.out.println(ip2.getHostName());
        System.out.println(ip2.getHostAddress());

        System.out.println("-------------------");

        //获取公网ip对象
        InetAddress ip3 = InetAddress.getByName("36.152.44.95");
        System.out.println(ip3.getHostName());
        System.out.println(ip3.getHostAddress());

        System.out.println("-------------------");

        //判断是否能通,ping 5秒之前测试是否可通
        System.out.println(ip3.isReachable(5000));

    }
}

1.2、端口号

端口号:

        标识正在计算机设备上运行的进程(程序),被规定为一个 16 位的二进制,范围是 0~65535。唯一标识正在计算机设备上运行的进程(程序)

端口类型

        周知端口:0~1023,被预先定义的知名应用占用(如:HTTP占用 80FTP占用21

        注册端口1024~49151,分配给用户进程或某些应用程序。(如:Tomcat占 用8080MySQL占用3306

        动态端口:49152到65535,之所以称为动态端口,是因为它 一般不固定分配某种进程,而是动态分配。

注意:我们自己开发的程序选择注册端口,且一个设备中不能出现两个程序的端口号一样,否则出错。

1.3、协议

通信协议:连接和通信数据的规则被称为网络通信协议

传输层的2个常见协议

TCP(Transmission Control Protocol) :传输控制协议

UDP(User Datagram Protocol):用户数据报协议

TCP协议特点

        使用TCP协议,必须双方先建立连接,它是一种面向连接可靠通信协议。

        传输前,采用“三次握手”方式建立连接,所以是可靠的 。

        在连接中可进行大数据量的传输 。

        连接、发送数据都需要确认,且传输完毕后,还需释放已建立的连接,通信效率较低。

TCP协议通信场景

        对信息安全要求较高的场景,例如:文件下载、金融等数据通信。

 

UDP协议:

        UDP是一种无连接不可靠传输的协议。

        将数据源IP、目的地IP和端口封装成数据包,不需要建立连接 每个数据包的大小限制在64KB

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

        可以广播发送 ,发送数据结束时无需释放资源,开销小,速度快。

UDP协议通信场景

        语音通话,视频会话等。

2.UDP通信 快速入门

2.1、快速入门

DatagramPacket:数据包对象

构造器

说明

public DatagramPacket(byte[] buf, int length, InetAddress address, int port)

创建发送端数据包对象

buf:要发送的内容,字节数组

length:要发送内容的字节长度

address:接收端的IP地址对象

port:接收端的端口号

public DatagramPacket(byte[] buf, int length)

创建接收端的数据包对象

buf:用来存储接收的内容

length:能够接收内容的长度

DatagramPacket常用方法

方法

说明

public int getLength()

获得实际接收到的字节个数

DatagramSocket发送端和接收端对象

构造器

说明

public DatagramSocket()

创建发送端的Socket对象,系统会随机分配一个端口号。

public DatagramSocket(int port)

创建接收端的Socket对象并指定端口号

DatagramSocket类成员方法

方法

说明

public void send(DatagramPacket dp)

发送数据包

public void receive(DatagramPacket p)

接收数据包

 

发送端

package com.itwpf.d2_udp1;

import java.io.IOException;
import java.net.*;
import java.nio.charset.StandardCharsets;

public class ClientDemo1 {
    public static void main(String[] args) throws IOException {
        //创建发送端对象,发送端自带默认的端口号
        DatagramSocket socket = new DatagramSocket();

        //创建一个数据对象封装数据
        /*
        public DatagramPacket(byte buf[], int length,
                          InetAddress address, int port)
         参数1:封装要发送的数据
         参数2:发送数据的大小
         参数3:服务端的主机IP地址
         参数4:服务端的端口
         */
        byte []buffer = "你好世界".getBytes();
        DatagramPacket packet = new DatagramPacket(buffer,buffer.length, InetAddress.getLocalHost(),8080);

        //发送数据出去
        socket.send(packet);

        //释放资源
        socket.close();

    }
}

接收端

package com.itwpf.d2_udp1;

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

public class ServerDemo1 {
    public static void main(String[] args) throws IOException {
        //创建接收端对象
        DatagramSocket socket = new DatagramSocket(8080);

        //创建一个数据包对象,接收数据
        byte[]buffer = new byte[1024*64];
        DatagramPacket packet = new DatagramPacket(buffer,buffer.length);

        //等待接收数据
        socket.receive(packet);

        int len = packet.getLength();

        String rs = new String(buffer,0,len);
        System.out.println(rs);

        SocketAddress socketAddress = packet.getSocketAddress();
        int port = packet.getPort();
        System.out.println(socketAddress);
        System.out.println(port);


        socket.close();

    }
}

2.2、多发多收

 

 发送端

package com.itwpf.d3_udp2;

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

public class ClientDemo1 {
    public static void main(String[] args) throws IOException {
        //创建发送端对象,发送端自带默认的端口号
        DatagramSocket socket = new DatagramSocket();


        Scanner scanner = new Scanner(System.in);
        while(true){
            System.out.println("请说:");
            String msg = scanner.nextLine();
            if("exit".equals(msg)){
                System.out.println("离线成功");
                socket.close();
                break;
            }
        //创建一个数据对象封装数据
        byte []buffer = msg.getBytes();
        DatagramPacket packet = new DatagramPacket(buffer,buffer.length, InetAddress.getLocalHost(),8080);

        //发送数据出去
        socket.send(packet);

        }
    }
}

接受端

package com.itwpf.d3_udp2;

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

public class ServerDemo1 {
    public static void main(String[] args) throws IOException {
        //创建接收端对象
        DatagramSocket socket = new DatagramSocket(8080);

        //创建一个数据包对象,接收数据
        byte[]buffer = new byte[1024*64];
        DatagramPacket packet = new DatagramPacket(buffer,buffer.length);

        while(true){
            //等待接收数据
            socket.receive(packet);

            int len = packet.getLength();

            String rs = new String(buffer,0,len);


            SocketAddress socketAddress = packet.getSocketAddress();
            int port = packet.getPort();
            System.out.println("收到了来自:"+socketAddress+" 对方端口:"+port+" 消息"+rs);

        }

    }
}

3.UDP通信 广播,组播

 

package com.itwpf.d4_udp_broadcast;

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

public class ClientDemo1 {
    public static void main(String[] args) throws IOException {
        //创建发送端对象,发送端自带默认的端口号
        DatagramSocket socket = new DatagramSocket();


        Scanner scanner = new Scanner(System.in);
        while(true){
            System.out.println("请说:");
            String msg = scanner.nextLine();
            if("exit".equals(msg)){
                System.out.println("离线成功");
                socket.close();
                break;
            }
        //创建一个数据对象封装数据
        byte []buffer = msg.getBytes();
        DatagramPacket packet = new DatagramPacket(buffer,buffer.length, InetAddress.getByName("255.255.255.255"),8080);

        //发送数据出去
        socket.send(packet);

        }
    }
}
package com.itwpf.d4_udp_broadcast;

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

public class ServerDemo1 {
    public static void main(String[] args) throws IOException {
        //创建接收端对象
        DatagramSocket socket = new DatagramSocket(8080);

        //创建一个数据包对象,接收数据
        byte[]buffer = new byte[1024*64];
        DatagramPacket packet = new DatagramPacket(buffer,buffer.length);

        while(true){
            //等待接收数据
            socket.receive(packet);

            int len = packet.getLength();

            String rs = new String(buffer,0,len);


            SocketAddress socketAddress = packet.getSocketAddress();
            int port = packet.getPort();
            System.out.println("收到了来自:"+socketAddress+" 对方端口:"+port+" 消息"+rs);

        }

    }
}

package com.itwpf.d5_udp_multicast;

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

public class ClientDemo1 {
    public static void main(String[] args) throws IOException {
        //创建发送端对象,发送端自带默认的端口号
        DatagramSocket socket = new DatagramSocket();


        Scanner scanner = new Scanner(System.in);
        while(true){
            System.out.println("请说:");
            String msg = scanner.nextLine();
            if("exit".equals(msg)){
                System.out.println("离线成功");
                socket.close();
                break;
            }
        //创建一个数据对象封装数据
        byte []buffer = msg.getBytes();
        DatagramPacket packet = new DatagramPacket(buffer,buffer.length, InetAddress.getByName("224.0.1.1"),8080);

        //发送数据出去
        socket.send(packet);

        }
    }
}
package com.itwpf.d5_udp_multicast;

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

public class ServerDemo1 {
    public static void main(String[] args) throws IOException {
        //创建接收端对象
        MulticastSocket socket = new MulticastSocket(8080);

        socket.joinGroup(InetAddress.getByName("224.0.1.1"));

        //创建一个数据包对象,接收数据
        byte[]buffer = new byte[1024*64];
        DatagramPacket packet = new DatagramPacket(buffer,buffer.length);

        while(true){
            //等待接收数据
            socket.receive(packet);

            int len = packet.getLength();

            String rs = new String(buffer,0,len);


            SocketAddress socketAddress = packet.getSocketAddress();
            int port = packet.getPort();
            System.out.println("收到了来自:"+socketAddress+" 对方端口:"+port+" 消息"+rs);

        }

    }
}

4.TCP通信 快速入门

TCP协议回顾:

TCP是一种面向连接,安全、可靠的传输数据的协议

传输前,采用“三次握手”方式,点对点通信,是可靠的

在连接中可进行大数据量的传输 

构造器

说明

public Socket(String host , int port)

创建发送端的Socket对象与服务端连接,

参数为服务端程序的ip和端口。

 

方法

说明

OutputStream getOutputStream()

获得字节输出流对象

InputStream getInputStream()

获得字节输入流对象

4.1、客户端

 

package com.itheima.d5_socket1;

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

/**
   目标:完成Socket网络编程入门案例的客户端开发,实现1发1收。
 */
public class ClientDemo1 {
    public static void main(String[] args) {
        try {
            System.out.println("====客户端启动===");
            // 1、创建Socket通信管道请求有服务端的连接
            // public Socket(String host, int port)
            // 参数一:服务端的IP地址
            // 参数二:服务端的端口
            Socket socket = new Socket("127.0.0.1", 7777);

            // 2、从socket通信管道中得到一个字节输出流 负责发送数据
            OutputStream os = socket.getOutputStream();

            // 3、把低级的字节流包装成打印流
            PrintStream ps = new PrintStream(os);

            // 4、发送消息
            ps.println("我是TCP的客户端,我已经与你对接,并发出邀请:约吗?");
            ps.flush();

            // 关闭资源。
            // socket.close();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

4.2、服务端

 

 

package com.itheima.d5_socket1;

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

/**
   目标:开发Socket网络编程入门代码的服务端,实现接收消息
 */
public class ServerDemo2 {
    public static void main(String[] args) {
        try {
            System.out.println("===服务端启动成功===");
            // 1、注册端口
            ServerSocket serverSocket = new ServerSocket(7777);
            // 2、必须调用accept方法:等待接收客户端的Socket连接请求,建立Socket通信管道
            Socket socket = serverSocket.accept();
            // 3、从socket通信管道中得到一个字节输入流
            InputStream is = socket.getInputStream();
            // 4、把字节输入流包装成缓冲字符输入流进行消息的接收
            BufferedReader br = new BufferedReader(new InputStreamReader(is));
            // 5、按照行读取消息
            String msg;
            if ((msg = br.readLine()) != null){
                System.out.println(socket.getRemoteSocketAddress() + "说了:: " + msg);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

5.TCP通信 多发多收消息

package com.itheima.d6_socket2;

import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;
import java.util.Scanner;

/**
   目标:实现多发和多收
 */
public class ClientDemo1 {
    public static void main(String[] args) {
        try {
            System.out.println("====客户端启动===");
            // 1、创建Socket通信管道请求有服务端的连接
            // public Socket(String host, int port)
            // 参数一:服务端的IP地址
            // 参数二:服务端的端口
            Socket socket = new Socket("127.0.0.1", 7777);

            // 2、从socket通信管道中得到一个字节输出流 负责发送数据
            OutputStream os = socket.getOutputStream();

            // 3、把低级的字节流包装成打印流
            PrintStream ps = new PrintStream(os);

            Scanner sc =  new Scanner(System.in);
            while (true) {
                System.out.println("请说:");
                String msg = sc.nextLine();
                // 4、发送消息
                ps.println(msg);
                ps.flush();
            }

            // 关闭资源。
            // socket.close();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
package com.itheima.d6_socket2;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

/**
   目标:开发Socket网络编程入门代码的服务端,实现接收消息
 */
public class ServerDemo2 {
    public static void main(String[] args) {
        try {
            System.out.println("===服务端启动成功===");
            // 1、注册端口
            ServerSocket serverSocket = new ServerSocket(7777);
            while (true) {
                // 2、必须调用accept方法:等待接收客户端的Socket连接请求,建立Socket通信管道
                Socket socket = serverSocket.accept();
                // 3、从socket通信管道中得到一个字节输入流
                InputStream is = socket.getInputStream();
                // 4、把字节输入流包装成缓冲字符输入流进行消息的接收
                BufferedReader br = new BufferedReader(new InputStreamReader(is));
                // 5、按照行读取消息
                String msg;
                while ((msg = br.readLine()) != null){
                    System.out.println(socket.getRemoteSocketAddress() + "说了:: " + msg);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

6.TCP通信 同时接受多个客户端消息

 主线程定义了循环负责接收客户端Socket管道连接

每接收到一个Socket通信管道后分配一个独立的线程负责处理它。

package com.itheima.d7_socket3;

import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;
import java.util.Scanner;

/**
    目标:实现服务端可以同时处理多个客户端的消息。
 */
public class ClientDemo1 {
    public static void main(String[] args) {
        try {
            System.out.println("====客户端启动===");
            // 1、创建Socket通信管道请求有服务端的连接
            // public Socket(String host, int port)
            // 参数一:服务端的IP地址
            // 参数二:服务端的端口
            Socket socket = new Socket("127.0.0.1", 7777);

            // 2、从socket通信管道中得到一个字节输出流 负责发送数据
            OutputStream os = socket.getOutputStream();

            // 3、把低级的字节流包装成打印流
            PrintStream ps = new PrintStream(os);

            Scanner sc =  new Scanner(System.in);
            while (true) {
                System.out.println("请说:");
                String msg = sc.nextLine();
                // 4、发送消息
                ps.println(msg);
                ps.flush();
            }

            // 关闭资源。
            // socket.close();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
package com.itheima.d7_socket3;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

/**
   目标:实现服务端可以同时处理多个客户端的消息。
 */
public class ServerDemo2 {
    public static void main(String[] args) {
        try {
            System.out.println("===服务端启动成功===");
            // 1、注册端口
            ServerSocket serverSocket = new ServerSocket(7777);
            // a.定义一个死循环由主线程负责不断的接收客户端的Socket管道连接。
            while (true) {
                // 2、每接收到一个客户端的Socket管道,交给一个独立的子线程负责读取消息
                Socket socket = serverSocket.accept();
                System.out.println(socket.getRemoteSocketAddress()+ "它来了,上线了!");
                // 3、开始创建独立线程处理socket
                new ServerReaderThread(socket).start();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
package com.itheima.d7_socket3;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.Socket;

public class ServerReaderThread extends Thread{
    private Socket socket;
    public ServerReaderThread(Socket socket){
        this.socket = socket;
    }
    @Override
    public void run() {
        try {
            // 3、从socket通信管道中得到一个字节输入流
            InputStream is = socket.getInputStream();
            // 4、把字节输入流包装成缓冲字符输入流进行消息的接收
            BufferedReader br = new BufferedReader(new InputStreamReader(is));
            // 5、按照行读取消息
            String msg;
            while ((msg = br.readLine()) != null){
                System.out.println(socket.getRemoteSocketAddress() + "说了:: " + msg);
            }
        } catch (Exception e) {
            System.out.println(socket.getRemoteSocketAddress() + "下线了!!!");
        }
    }
}

存在问题:

客户端并发越,系统瘫痪的越快

户端与服务端的线程模型是: N-N的关系

7.TCP通信 使用线程池优化

package com.itheima.d8_socket4;

import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;
import java.util.Scanner;

/**
    拓展:使用线程池优化:实现通信。
 */
public class ClientDemo1 {
    public static void main(String[] args) {
        try {
            System.out.println("====客户端启动===");
            // 1、创建Socket通信管道请求有服务端的连接
            // public Socket(String host, int port)
            // 参数一:服务端的IP地址
            // 参数二:服务端的端口
            Socket socket = new Socket("127.0.0.1", 6666);

            // 2、从socket通信管道中得到一个字节输出流 负责发送数据
            OutputStream os = socket.getOutputStream();

            // 3、把低级的字节流包装成打印流
            PrintStream ps = new PrintStream(os);

            Scanner sc =  new Scanner(System.in);
            while (true) {
                System.out.println("请说:");
                String msg = sc.nextLine();
                // 4、发送消息
                ps.println(msg);
                ps.flush();
            }
            // 关闭资源。
            // socket.close();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
package com.itheima.d8_socket4;
import com.itheima.d7_socket3.ServerReaderThread;

import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.*;

/**
   目标:实现服务端可以同时处理多个客户端的消息。
 */
public class ServerDemo2 {

    // 使用静态变量记住一个线程池对象
    private static ExecutorService pool = new ThreadPoolExecutor(300,
            1500, 6, TimeUnit.SECONDS,
            new ArrayBlockingQueue<>(2),
            Executors.defaultThreadFactory(),
            new ThreadPoolExecutor.AbortPolicy());

    public static void main(String[] args) {
        try {
            System.out.println("===服务端启动成功===");
            // 1、注册端口
            ServerSocket serverSocket = new ServerSocket(6666);
            // a.定义一个死循环由主线程负责不断的接收客户端的Socket管道连接。
            while (true) {
                // 2、每接收到一个客户端的Socket管道,
                Socket socket = serverSocket.accept();
                System.out.println(socket.getRemoteSocketAddress()+ "它来了,上线了!");

                // 任务对象负责读取消息。
                Runnable target = new ServerReaderRunnable(socket);
                pool.execute(target);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
package com.itheima.d8_socket4;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.Socket;

public class ServerReaderRunnable implements Runnable{
    private Socket socket;
    public ServerReaderRunnable(Socket socket){
        this.socket = socket;
    }
    @Override
    public void run() {
        try {
            // 3、从socket通信管道中得到一个字节输入流
            InputStream is = socket.getInputStream();
            // 4、把字节输入流包装成缓冲字符输入流进行消息的接收
            BufferedReader br = new BufferedReader(new InputStreamReader(is));
            // 5、按照行读取消息
            String msg;
            while ((msg = br.readLine()) != null){
                System.out.println(socket.getRemoteSocketAddress() + "说了:: " + msg);
            }
        } catch (Exception e) {
            System.out.println(socket.getRemoteSocketAddress() + "下线了!!!");
        }
    }
}

8.TCP通信 模拟BS系统

 

 

package com.itheima.d10_bs;

import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.*;

/**
    了解:BS-浏览器-服务器基本了解。

    引入:
        之前客户端和服务端都需要自己开发。也就是CS架构。
        接下来模拟一下BS架构。

    客户端:浏览器。(无需开发)
    服务端:自己开发。
    需求:在浏览器中请求本程序,响应一个网页文字给浏览器显示


 */
public class BSserverDemo {
    // 使用静态变量记住一个线程池对象
    private static ExecutorService pool = new ThreadPoolExecutor(3,
            5, 6, TimeUnit.SECONDS,
            new ArrayBlockingQueue<>(2), 
            Executors.defaultThreadFactory(), 
            new ThreadPoolExecutor.AbortPolicy());

    public static void main(String[] args) {
        try {
            // 1.注册端口
            ServerSocket ss = new ServerSocket(8080);
            // 2.创建一个循环接收多个客户端的请求。
            while(true){
                Socket socket = ss.accept();
                // 3.交给一个独立的线程来处理!
                pool.execute(new ServerReaderRunnable(socket));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

package com.itheima.d10_bs;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;

public class ServerReaderRunnable implements Runnable{
    private Socket socket;
    public ServerReaderRunnable(Socket socket){
        this.socket = socket;
    }
    @Override
    public void run() {
        try {
            // 浏览器 已经与本线程建立了Socket管道
            // 响应消息给浏览器显示
            PrintStream ps = new PrintStream(socket.getOutputStream());
            // 必须响应HTTP协议格式数据,否则浏览器不认识消息
            ps.println("HTTP/1.1 200 OK"); // 协议类型和版本 响应成功的消息!
            ps.println("Content-Type:text/html;charset=UTF-8"); // 响应的数据类型:文本/网页

            ps.println(); // 必须发送一个空行

            // 才可以响应数据回去给浏览器
            ps.println("<span style='color:red;font-size:90px'>《你是最牛的!!!!》 </span>");
            ps.close();
        } catch (Exception e) {
            System.out.println(socket.getRemoteSocketAddress() + "下线了!!!");
        }
    }
}

在浏览器上访问8080端口:http://127.0.0.1:8080,即可出现以下效果

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值