网络编程
网络通信基本模式
*CS模式:*客户端和服务端模式,客户端和服务端都由程序员开发,用户需要安装客户端
*BS模式:*用户通过浏览器访问服务端,服务端由程序员开发
网络通信三要素
IP地址
设备在网络中的地址,是唯一标识
常用ip命令:
查看本机IP地址:ipconfig
检查网络是否连通:ping IP地址
局域网网址
192.168. 开头的就是常见的局域网地址,范围即为192.168.0.0–192.168.255.255,专门为组织机构内部使用
特殊IP地址
本机IP: 127.0.0.1或者localhost:称为回送地址也可称本地回环地址,只会寻找当前所在本机。
IP地址操作类:InetAddress
package com.itheima.inetadress;
import java.net.InetAddress;
/**
目标:InetAddress类概述(了解)
一个该类的对象就代表一个IP地址对象。
InetAddress类成员方法:
static InetAddress getLocalHost()
* 获得本地主机IP地址对象。
static InetAddress getByName(String host)
* 根据IP地址字符串或主机名获得对应的IP地址对象。
String getHostName()
* 获得主机名。
String getHostAddress()
* 获得IP地址字符串。
*/
public class Demo01 {
public static void main(String[] args) throws Exception {
//获取本地主机IP地址对象
InetAddress localHost = InetAddress.getLocalHost();
System.out.println(localHost);
System.out.println(localHost.getHostAddress());
System.out.println(localHost.getHostName());
//根据IP地址字符串或主机名获得相应的IP地址对象
InetAddress ip1 = InetAddress.getByName("www.baidu.com");
System.out.println(ip1.getHostName());
System.out.println(ip1.getHostAddress());
}
}
端口号
应用程序在设备中的唯一标识,被规定为一个 16 位的二进制,范围是 0~65535。
端口类型
周知端口:0~1023,被预先定义的知名应用占用(如:HTTP占用 80,FTP占用21)
注册端口:1024~49151,分配给用户进程或某些应用程序。(如:Tomcat占 用8080,MySQL占用3306)
动态端口:49152到65535,之所以称为动态端口,是因为它 一般不固定分配某种进程,而是动态分配。
注意:我们自己开发的程序选择注册端口,且一个设备中不能出现两个程序的端口号一样,否则出错。
协议
数据在网络中传输的规则,常见协议有:TCP,UDP
网络通信参考模型
OSI参考模型:世界互联协议标准,全球通信规范,由于此模型过于理想化,未能在因特网上进行广泛推广。
TCP/IP参考模型(或TCP/IP协议):事实上的国际标准。
传输层的两个常见协议
TCP(Transmission Control Protocol) :传输控制协议
UDP(User Datagram Protocol):用户数据报协议
TCP协议特点
使用TCP协议,必须双方先建立连接,它是一种面向连接的可靠通信协议。
传输前,采用“三次握手”方式建立连接,所以是可靠的 。
在连接中可进行大数据量的传输 。
连接、发送数据都需要确认,且传输完毕后,还需释放已建立的连接,通信效率较低。
TCP协议通信场景
对信息安全要求较高的场景,例如:文件下载、金融等数据通信。
UDP协议特点
UDP是一种无连接、不可靠传输的协议。
将数据源IP、目的地IP和端口封装成数据包,不需要建立连接
每个数据包的大小限制在64KB内
发送不管对方是否准备好,接收方收到也不确认,故是不可靠的
可以广播发送 ,发送数据结束时无需释放资源,开销小,速度快。
UDP协议通信场景
语音通话,视频会话等。
UDP通信
使用UDP通信实现发送消息、接收消息(一发一收)
package com.itheima.udp.demo01;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
/**
* 发送端 一发一收
*/
public class Client {
public static void main(String[] args) throws Exception {
System.out.println("=======客户端启动======");
//创建发送端对象,发送端自带默认端口号
DatagramSocket socket = new DatagramSocket();
byte[] bytes = "UDP协议数据发送测试".getBytes();
/*
创建数据包对象
public DatagramPacket(byte buf[], int length,
InetAddress address, int port) {}
参数一:数据字节数组,参数二:发送长度,参数三:对方IP地址,参数四:对方端口号
*/
DatagramPacket packet = new DatagramPacket(bytes,bytes.length, InetAddress.getLocalHost(),9999);
//发送数据
socket.send(packet);
System.out.println("数据已发送");
socket.close();
}
}
package com.itheima.udp.demo01;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
/**
* 服务端
*/
public class Server {
public static void main(String[] args) throws Exception {
System.out.println("=====服务端启动=====");
//创建接收端对象
DatagramSocket socket = new DatagramSocket(9999);
//创建数据包对象
byte[] bytes = new byte[1024 * 64];
DatagramPacket packet = new DatagramPacket(bytes,bytes.length);
//等待接收数据
System.out.println("等待接收数据");
socket.receive(packet);
//取出数据
String s = new String(bytes);
System.out.println("接收到数据:"+s);
System.out.println("对方IP地址:"+packet.getAddress());
System.out.println("对方端口:"+packet.getPort());
socket.close();
}
}
使用UDP通信实现发送消息、接收消息(多发多收)
package com.itheima.udp.demo02;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
/**
* 服务端 多发多收
*/
public class Server {
public static void main(String[] args) throws Exception {
System.out.println("=====服务端启动=====");
//创建接收端对象
DatagramSocket socket = new DatagramSocket(9999);
//创建数据包对象
byte[] bytes = new byte[1024 * 64];
DatagramPacket packet = new DatagramPacket(bytes,bytes.length);
while (true) {
//等待接收数据
socket.receive(packet);
//取出数据
String s = new String(bytes);
System.out.println("接收到来自IP地址为"+packet.getAddress()+",端口为:"+packet.getPort()+"的消息:"+s);
}
}
}
package com.itheima.udp.demo02;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner;
/**
* 发送端 多发多收
*/
public class Client {
public static void main(String[] args) throws Exception {
System.out.println("=======客户端启动======");
//创建发送端对象,发送端自带默认端口号
DatagramSocket socket = new DatagramSocket();
Scanner sc = new Scanner(System.in);
while (true) {
System.out.println("请输入消息:");
String s = sc.nextLine();
if ("exit".equals(s)) {
socket.close();
System.out.println("拜拜");
break;
}
//创建数据包对象
byte[] bytes = s.getBytes();
DatagramPacket packet = new DatagramPacket(bytes,bytes.length, InetAddress.getLocalHost(),9999);
//发送数据
socket.send(packet);
System.out.println("消息已发送");
}
}
}
UDP广播
package com.itheima.udp.demo03broadcast;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner;
/**
* 发送端 广播
* 发送端目的IP使用广播IP:"255.255.255.255"
* 同一网段下其他主机使用对应端口即可接收广播消息
*/
public class Client {
public static void main(String[] args) throws Exception {
System.out.println("=======客户端启动======");
//创建发送端对象,发送端自带默认端口号
DatagramSocket socket = new DatagramSocket();
Scanner sc = new Scanner(System.in);
while (true) {
System.out.println("请输入广播消息:");
String s = sc.nextLine();
if ("exit".equals(s)) {
socket.close();
System.out.println("拜拜");
break;
}
//创建数据包对象
byte[] bytes = s.getBytes();
DatagramPacket packet = new DatagramPacket(bytes,bytes.length, InetAddress.getByName("255.255.255.255"),9999);
//发送数据
socket.send(packet);
System.out.println("消息已发送");
}
}
}
package com.itheima.udp.demo03broadcast;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
/**
* 服务端 接收广播消息
*/
public class Server {
public static void main(String[] args) throws Exception {
System.out.println("=====服务端启动=====");
//创建接收端对象
DatagramSocket socket = new DatagramSocket(9999);
//创建数据包对象
byte[] bytes = new byte[1024 * 64];
DatagramPacket packet = new DatagramPacket(bytes,bytes.length);
while (true) {
//等待接收数据
socket.receive(packet);
//取出数据
String s = new String(bytes);
System.out.println("接收到来自IP地址为"+packet.getAddress()+",端口为:"+packet.getPort()+"的消息:"+s);
}
}
}
UDP组播
package com.itheima.udp.demo04multicast;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner;
/**
* 发送端 组播
* 发送端目的IP使用组播IP:"224.0.0.0"-"239.255.255.255"并指定端口
* 同一网段下其他主机注册该IP以及端口即可接收组播消息
*/
public class Client {
public static void main(String[] args) throws Exception {
System.out.println("=======客户端启动======");
//创建发送端对象,发送端自带默认端口号
DatagramSocket socket = new DatagramSocket();
Scanner sc = new Scanner(System.in);
while (true) {
System.out.println("请输入组播消息:");
String s = sc.nextLine();
if ("exit".equals(s)) {
socket.close();
System.out.println("拜拜");
break;
}
//创建数据包对象
byte[] bytes = s.getBytes();
DatagramPacket packet = new DatagramPacket(bytes,bytes.length, InetAddress.getByName("224.2.2.2"),9999);
//发送数据
socket.send(packet);
System.out.println("消息已发送");
}
}
}
package com.itheima.udp.demo04multicast;
import java.net.*;
/**
* 服务端 接收广播消息
*/
public class Server {
public static void main(String[] args) throws Exception {
System.out.println("=====服务端启动=====");
//创建接收端对象
MulticastSocket socket = new MulticastSocket(9999);
// socket.joinGroup(InetAddress.getByName("224.2.2.2"));这种写法从JDK14开始过时
/**
public void joinGroup(SocketAddress mcastaddr, NetworkInterface netIf)
参数一:组播IP地址和端口
参数二:接收指定网段里的组播消息
*/
socket.joinGroup(new InetSocketAddress(InetAddress.getByName("224.2.2.2"),9999),NetworkInterface.getByInetAddress(InetAddress.getLocalHost()));
//创建数据包对象
byte[] bytes = new byte[1024 * 64];
DatagramPacket packet = new DatagramPacket(bytes,bytes.length);
while (true) {
//等待接收数据
socket.receive(packet);
//取出数据
String s = new String(bytes);
System.out.println("接收到来自IP地址为"+packet.getAddress()+",端口为:"+packet.getPort()+"的消息:"+s);
}
}
}
TCP通信
使用TCP通信实现发送消息、接收消息(一发一收)
客户端代表类:Socket类
服务端代表类:ServerSocket类
客户端类
package com.itheima.tcp.demo01socket;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;
/**
* 发送端 一发一收
*/
public class Client {
public static void main(String[] args) {
System.out.println("客户端已启动");
try {
//创建Socket通信管道,请求服务端连接,参数一:服务器的IP,参数二:服务器端口
Socket socket = new Socket("127.0.0.1", 8888);
//从管道中获取一个字节输出流,用于发送数据
OutputStream os = socket.getOutputStream();
//将低级字节输出流封装为打印流
PrintStream ps = new PrintStream(os);
//发送数据,这里发送的是一行消息,服务端应该同样接收一行消息,格式要一致
ps.println("这是一条TCP测试消息");
ps.flush();
System.out.println("发送成功");
//关闭资源,不建议关闭
// socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
服务端类
package com.itheima.tcp.demo01socket;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 服务端
*/
public class Server {
public static void main(String[] args) {
System.out.println("服务端已启动");
try {
//注册端口
ServerSocket serverSocket = new ServerSocket(8888);
//调用accept方法,等待客户端的socket连接请求,建立Socket通信管道
Socket socket = serverSocket.accept();
//从Socket管道中获取一个字节输入流,用于接收数据
InputStream is = socket.getInputStream();
//将低级字节输入流封装成缓冲字符输入流
BufferedReader br = new BufferedReader(new InputStreamReader(is));
//接收数据
String s;
if ((s = br.readLine())!=null){
System.out.println("收到来自IP地址为:"+socket.getRemoteSocketAddress()+"的消息:"+s);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
使用TCP通信实现发送消息、接收消息(多发多收,服务端与多个客户端通信)
客户端类
package com.itheima.tcp.demo02socket;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;
import java.util.Scanner;
/**
* 客户端 多发多收
*/
public class Client {
public static void main(String[] args) {
System.out.println("客户端已启动");
try {
//创建Socket通信管道,请求服务端连接,参数一:服务器的IP,参数二:服务器端口
Socket socket = new Socket("127.0.0.1", 8888);
//从管道中获取一个字节输出流,用于发送数据
OutputStream os = socket.getOutputStream();
//将低级字节输出流封装为打印流
PrintStream ps = new PrintStream(os);
//发送数据,这里发送的是一行消息,服务端应该同样接收一行消息,格式要一致
Scanner sc = new Scanner(System.in);
while (true) {
System.out.println("请输入消息:");
String s = sc.nextLine();
ps.println(s);
ps.flush();
System.out.println("发送成功");
}
//关闭资源,不建议关闭
// socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
服务端类
package com.itheima.tcp.demo02socket;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.*;
/**
* 服务端 实现服务端与多个客户端通信
*/
public class Server {
public static void main(String[] args) {
System.out.println("服务端已启动");
try {
//注册端口
ServerSocket serverSocket = new ServerSocket(8888);
//主线程使用死循环等待客户端连接
while (true) {
//调用accept方法,等待客户端的socket连接请求,建立Socket通信管道
Socket socket = serverSocket.accept();
System.out.println("IP地址为:"+socket.getRemoteSocketAddress()+"的用户上线了");
//创建子线程接收客户端消息
new SocketReaderThread(socket).start();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
线程类
package com.itheima.tcp.demo02socket;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.Socket;
public class SocketReaderThread extends Thread {
private Socket socket;
public SocketReaderThread(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
//从Socket管道中获取一个字节输入流,用于接收数据
InputStream is = socket.getInputStream();
//将低级字节输入流封装成缓冲字符输入流
BufferedReader br = new BufferedReader(new InputStreamReader(is));
//接收数据
String s;
while ((s = br.readLine())!=null){
System.out.println("收到来自IP地址为:"+socket.getRemoteSocketAddress()+"的消息:"+s);
}
} catch (Exception e) {
//当客户端关闭后,服务端线程会抛出异常同步关闭,以此判定客户端下线
System.out.println("IP地址为:"+socket.getRemoteSocketAddress()+"的用户下线了");
}
}
}
使用线程池优化服务端与多个客户端通信,解决并发问题
客户端
package com.itheima.tcp.demo03socket;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;
import java.util.Scanner;
/**
* 客户端 多发多收
*/
public class Client {
public static void main(String[] args) {
System.out.println("客户端已启动");
try {
//创建Socket通信管道,请求服务端连接,参数一:服务器的IP,参数二:服务器端口
Socket socket = new Socket("127.0.0.1", 8888);
//从管道中获取一个字节输出流,用于发送数据
OutputStream os = socket.getOutputStream();
//将低级字节输出流封装为打印流
PrintStream ps = new PrintStream(os);
//发送数据,这里发送的是一行消息,服务端应该同样接收一行消息,格式要一致
Scanner sc = new Scanner(System.in);
while (true) {
System.out.println("请输入消息:");
String s = sc.nextLine();
ps.println(s);
ps.flush();
System.out.println("发送成功");
}
//关闭资源,不建议关闭
// socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
服务端
package com.itheima.tcp.demo03socket;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.*;
/**
* 服务端 使用线程池优化实现服务端与多个客户端通信
*/
public class Server {
//定义一个线程池
private static ExecutorService pool = new ThreadPoolExecutor(3,5,3, TimeUnit.SECONDS, new ArrayBlockingQueue<>(1), Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());
public static void main(String[] args) {
System.out.println("服务端已启动");
try {
//注册端口
ServerSocket serverSocket = new ServerSocket(8888);
//主线程使用死循环等待客户端连接
while (true) {
//调用accept方法,等待客户端的socket连接请求,建立Socket通信管道
Socket socket = serverSocket.accept();
System.out.println("IP地址为:"+socket.getRemoteSocketAddress()+"的用户上线了");
//创建线程任务并执行
pool.execute(new SocketReaderRunnable(socket));
}
} catch (Exception e) {
System.out.println("人满了,别来了");
}
}
}
线程任务类
package com.itheima.tcp.demo03socket;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.Socket;
public class SocketReaderRunnable implements Runnable{
private Socket socket;
public SocketReaderRunnable(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
//从Socket管道中获取一个字节输入流,用于接收数据
InputStream is = socket.getInputStream();
//将低级字节输入流封装成缓冲字符输入流
BufferedReader br = new BufferedReader(new InputStreamReader(is));
//接收数据
String s;
while ((s = br.readLine())!=null){
System.out.println("收到来自IP地址为:"+socket.getRemoteSocketAddress()+"的消息:"+s);
}
} catch (Exception e) {
//当客户端关闭后,服务端线程会抛出异常同步关闭,以此判定客户端下线
System.out.println("IP地址为:"+socket.getRemoteSocketAddress()+"的用户下线了");
}
}
}
实现TCP即时通信
客户端类
package com.itheima.tcp.demo04socket;
import java.io.*;
import java.net.Socket;
import java.util.Scanner;
/**
* 客户端 多发多收
* 即时通信,客户端可收取来自其他客户端的消息
*/
public class Client {
public static void main(String[] args) {
System.out.println("客户端已启动");
try {
//创建Socket通信管道,请求服务端连接,参数一:服务器的IP,参数二:服务器端口
Socket socket = new Socket("192.168.90.56", 8888);
//创建一个子线程用于随时接收服务端的消息
new SocketReaderThread(socket).start();
//从管道中获取一个字节输出流,用于发送数据
OutputStream os = socket.getOutputStream();
//将低级字节输出流封装为打印流
PrintStream ps = new PrintStream(os);
//发送数据,这里发送的是一行消息,服务端应该同样接收一行消息,格式要一致
Scanner sc = new Scanner(System.in);
while (true) {
System.out.println("请输入消息:");
String s = sc.nextLine();
ps.println(s);
ps.flush();
System.out.println("发送成功");
}
//关闭资源,不建议关闭
// socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
客户端接收数据线程类
package com.itheima.tcp.demo04socket;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.Socket;
public class SocketReaderThread extends Thread {
private Socket socket;
public SocketReaderThread(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
//从Socket管道中获取一个字节输入流,用于接收数据
InputStream is = socket.getInputStream();
//将低级字节输入流封装成缓冲字符输入流
BufferedReader br = new BufferedReader(new InputStreamReader(is));
//接收数据
String s;
while ((s = br.readLine())!=null){
System.out.println(socket.getRemoteSocketAddress());
System.out.println("收到消息:"+s);
}
} catch (Exception e) {
System.out.println("你被服务端断开了");
}
}
}
服务端类
package com.itheima.tcp.demo04socket;
import sun.util.resources.cldr.zh.TimeZoneNames_zh;
import java.net.ServerSocket;
import java.net.Socket;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Date;
import java.util.concurrent.*;
/**
* 服务端 使用线程池优化实现服务端与多个客户端通信
*/
public class Server {
//定义一个线程池
private static ExecutorService pool = new ThreadPoolExecutor(3,5,3, TimeUnit.SECONDS, new ArrayBlockingQueue<>(1), Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());
//定义一个集合存储所有在线的Socket线程通道
public static ArrayList<Socket> allOnlineSockets = new ArrayList<>();
public static void main(String[] args) {
System.out.println("服务端已启动");
try {
//注册端口
ServerSocket serverSocket = new ServerSocket(8888);
//主线程使用死循环等待客户端连接
while (true) {
//调用accept方法,等待客户端的socket连接请求,建立Socket通信管道
Socket socket = serverSocket.accept();
System.out.println("IP地址为:"+socket.getRemoteSocketAddress()+"的用户上线了");
allOnlineSockets.add(socket);
//创建线程任务并执行
pool.execute(new SocketReaderRunnable(socket));
}
} catch (Exception e) {
System.out.println("人满了,别来了");
e.printStackTrace();
}
}
}
线程任务类
package com.itheima.tcp.demo04socket;
import java.io.*;
import java.net.Socket;
import java.net.SocketAddress;
public class SocketReaderRunnable implements Runnable{
private Socket socket;
public SocketReaderRunnable(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
//从Socket管道中获取一个字节输入流,用于接收数据
InputStream is = socket.getInputStream();
//将低级字节输入流封装成缓冲字符输入流
BufferedReader br = new BufferedReader(new InputStreamReader(is));
//接收数据
String s;
while ((s = br.readLine())!=null){
System.out.println("收到来自IP地址为:"+socket.getRemoteSocketAddress()+"的消息:"+s);
//端口转发
sendMsgToAll(s,socket.getRemoteSocketAddress());
}
} catch (Exception e) {
//当客户端关闭后,服务端线程会抛出异常同步关闭,以此判定客户端下线
System.out.println("IP地址为:"+socket.getRemoteSocketAddress()+"的用户下线了");
Server.allOnlineSockets.remove(socket);
}
}
private void sendMsgToAll(String s, SocketAddress remoteSocketAddress) throws Exception {
for (Socket socket : Server.allOnlineSockets) {
if (!remoteSocketAddress.equals(socket.getRemoteSocketAddress())){
PrintStream ps = new PrintStream(socket.getOutputStream());
ps.println(s);
ps.flush();
}
}
}
}
BS模式模拟
服务端类
package com.itheima.tcp.demo05socket;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.concurrent.*;
/**
* 服务端 使用线程池优化
*
*/
public class BSServer {
//定义一个线程池
private static ExecutorService pool = new ThreadPoolExecutor(3,5,3, TimeUnit.SECONDS, new ArrayBlockingQueue<>(1), Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());
public static void main(String[] args) {
System.out.println("服务端已启动");
try {
//注册端口
ServerSocket serverSocket = new ServerSocket(8888);
//主线程使用死循环等待客户端连接
while (true) {
//调用accept方法,等待浏览器的socket连接请求,建立Socket通信管道
Socket socket = serverSocket.accept();
//创建线程任务并执行
pool.execute(new SocketReaderRunnable(socket));
}
} catch (Exception e) {
System.out.println("人满了,别来了");
e.printStackTrace();
}
}
}
线程任务类
package com.itheima.tcp.demo05socket;
import com.itheima.tcp.demo04socket.Server;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.net.SocketAddress;
public class SocketReaderRunnable implements Runnable{
private Socket socket;
public SocketReaderRunnable(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
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:yellow;font-size:90px'>又快睡着了吧林总</span>");
ps.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}