黑马教程强化day5-2
目录
- 一、网络编程
- 1.UDP通信的实现
- 代码演示1
- 代码演示2:
- 2.TCP通信的实现
- 代码演示1:
- 代码演示2:
- 3.TCP通信-支持与多个客户端同时通信
- 代码演示1
- 4.BS架构的原理
- 代码演示
- 5.优化第4单元
- 代码演示
一、网络编程
1.UDP通信的实现
java提供了一个java.net.DatagramSocket类来实现UDP通信
- DatagramSocket:用于创建客户端、服务端
构造器:
- public DatagramSocket():创建客户端的Socket对象,系统会随机分配一个端口号。
- public DatagramSocket(int port):创建服务段的Socket对象,并指定端口号。
方法:
- public void sent(DatagramPacket dp):发送数据包
- public void receive(DatagramPacket P):使用数据包接受数据
- DatagramPacket创建数据包
- public DatagramPacket(byte[] buf,int length,InetAddress address,int port):创建发出去的数据包对象
- public DatagramPacket(byte[] buf,int length):创建用来接受数据的数据包。
代码演示1
单发单收:
UDPdemoClient1类:
package com.item.Inter2demoUDP;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class UDPdemoClient1 {public static void main(String[] args) throws Exception {//单发System.out.println("==客户端启动==");//1.创建发送端对象DatagramSocket socket=new DatagramSocket();//2.创建数据包对象,要发送数据包对象。byte[] bytes="今晚吃小龙虾".getBytes();DatagramPacket packet=new DatagramPacket(bytes, bytes.length, InetAddress.getLocalHost(),8080);//3.让发送端对象发送数据包的数据。socket.send(packet);socket.close();}
}
UDPdemoServers2类
package com.item.Inter2demoUDP;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
public class UDPdemoServers2 {public static void main(String[] args) throws Exception {//单收System.out.println("==服务端启动==");//1,接受端对象。DatagramSocket socket=new DatagramSocket(8080);//2.创建一个数据包对象负责接收数据byte[] buf=new byte[1024*64];DatagramPacket packet=new DatagramPacket(buf,buf.length);//3.接受数据socket.receive(packet);//4,查看数据int len=packet.getLength();//获取接受数据的长度与String data =new String(buf,0,len);System.out.println("发送给的数据"+data);//5.获取对方的IP对象和端口号String ip=packet.getAddress().getHostAddress();int port=packet.getPort();System.out.println("对方ip"+ip+" 对方端口"+port);socket.close();}
}
代码演示2:
多发多收:
UDPdemoClient1类:
package com.item.Inter3demoUDP2;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner;
public class UDPdemoClient1 {public static void main(String[] args) throws Exception {//多发System.out.println("==客户端启动==");//1.创建发送端对象DatagramSocket socket=new DatagramSocket();Scanner sc =new Scanner(System.in);while (true) {System.out.println("请说");String msg=sc.nextLine();//如果用户输入的是exit,则推出if("exit".equals(msg)){System.out.println("==客户端退出==");socket.close();break;}//2.创建数据包对象,要发送数据包对象。byte[] bytes=msg.getBytes();DatagramPacket packet=new DatagramPacket(bytes, bytes.length, InetAddress.getLocalHost(),8080);//3.让发送端对象发送数据包的数据。socket.send(packet);}}
}
UDPdemoServers2类:
package com.item.Inter3demoUDP2;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class UDPdemoServers2 {public static void main(String[] args) throws Exception {//多收System.out.println("==服务端启动==");//1,接受端对象。DatagramSocket socket=new DatagramSocket(8080);//2.创建一个数据包对象负责接收数据byte[] buf=new byte[1024*64];DatagramPacket packet=new DatagramPacket(buf,buf.length);while (true) {//3.接受数据socket.receive(packet);//4,查看数据int len=packet.getLength();//获取接受数据的长度与String data =new String(buf,0,len);System.out.println("发送给的数据"+data);//5.获取对方的IP对象和端口号String ip=packet.getAddress().getHostAddress();int port=packet.getPort();System.out.println("对方ip"+ip+" 对方端口"+port);System.out.println("===================");}}
}
2.TCP通信的实现
java提供一个java.net.Socket类来实现TCP通信。
客户端构造器:
- public Socket(String host,int port):指定服务器地址和端口号,请求与服务器建立连接,连接通过,就获得客户端socket
方法:
- public OutputStream getOutputStream():获取网络字节输出流
- public InputStream getInputStream():获取网络字节输入流
服务端构造器:
- public ServerSocket(int port):为服务程序注册端口
- public Socket accept():监听客户端请求,一旦与某个客户端成功连接,则返回服务器端这边的Socket对象
代码演示1:
TCPdemo1类:
客户端单发
package com.item.Inter4demoTCP1;
import java.net.InetAddress;
import java.net.Socket;
import java.io.*;
public class TCPdemo1 {public static void main(String[] args) throws Exception {//客户端System.out.println("==客户端启动==");//1.创建Socket管道对象,请求与服务端的Socket连接,可靠连接。Socket socket=new Socket(InetAddress.getLocalHost(),8080);//2.从socket通信管道中的到一个字节输出流。OutputStream os=socket.getOutputStream();//3.特殊数据流,把数据写入到字节输出流中。DataOutputStream dos=new DataOutputStream(os);dos.writeInt(1);dos.writeUTF("我想你");//4.关闭流资源socket.close();}
}
TCPdemoSe2 类:
服务端单收
package com.item.Inter4demoTCP1;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.security.Provider;
public class TCPdemoSe2 {public static void main(String[] args) throws IOException {//服务端System.out.println("==服务端启动==");//1.创建服务端对象,绑定端口号,监听客户端连接ServerSocket ss=new ServerSocket(8080);//2.等待客户端连接,调用accept方法,阻塞等待客户端连接,一旦有客户端连接,返回Socket对象Socket socket=ss.accept();//3.获取输入流,读取数据InputStream is=socket.getInputStream();//4.把字节输入流包装成特殊数据输入流DataInputStream dis=new DataInputStream(is);//5.读取数据int id=dis.readInt();String msg=dis.readUTF();System.out.println("id="+id+",msg="+msg);//6.客户端的ip和端口System.out.println("客户端的ip和端口"+socket.getInetAddress().getHostAddress()+":"+socket.getPort());}
}
代码演示2:
多发多收
TCPdemo1类
package com.item.Inter5demoTCP2;import java.io.DataOutputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.util.Scanner;public class TCPdemo1 {public static void main(String[] args) throws Exception {//客户多发System.out.println("==客户端启动==");//1.创建Socket管道对象,请求与服务端的Socket连接,可靠连接。Socket socket=new Socket(InetAddress.getLocalHost(),8080);//2.从socket通信管道中的到一个字节输出流。OutputStream os=socket.getOutputStream();//3.特殊数据流,把数据写入到字节输出流中。DataOutputStream dos=new DataOutputStream(os);Scanner sc=new Scanner(System.in);while (true) {System.out.println("请说:");String msg=sc.next();if("exit".equals( msg)){System.out.println("退出成功");dos.close();//关闭输出流socket.close();//关闭socketbreak;}dos.writeUTF(msg);dos.flush();//刷新管道}}
}
TCPdemoSe2类:
package com.item.Inter5demoTCP2;import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;public class TCPdemoSe2 {public static void main(String[] args) throws IOException {//服务多收System.out.println("==服务端启动==");//1.创建服务端对象,绑定端口号,监听客户端连接ServerSocket ss=new ServerSocket(8080);//2.等待客户端连接,调用accept方法,阻塞等待客户端连接,一旦有客户端连接,返回Socket对象Socket socket=ss.accept();//3.获取输入流,读取数据InputStream is=socket.getInputStream();//4.把字节输入流包装成特殊数据输入流DataInputStream dis=new DataInputStream(is);while (true) {//5.读取数据String msg=dis.readUTF();System.out.println(",msg="+msg);//6.客户端的ip和端口System.out.println("客户端的ip和端口"+socket.getInetAddress().getHostAddress()+":"+socket.getPort());System.out.println("-------------------");}}
}
3.TCP通信-支持与多个客户端同时通信
引入多线程。
代码演示1
多个用户客户端多发
TCPdemo1类:
package com.item.Inter6demoTCP3;
import java.io.DataOutputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.util.Scanner;
public class TCPdemo1 {public static void main(String[] args) throws Exception {//客户多发,System.out.println("==客户端启动==");//1.创建Socket管道对象,请求与服务端的Socket连接,可靠连接。Socket socket=new Socket(InetAddress.getLocalHost(),8080);//2.从socket通信管道中的到一个字节输出流。OutputStream os=socket.getOutputStream();//3.特殊数据流,把数据写入到字节输出流中。DataOutputStream dos=new DataOutputStream(os);Scanner sc=new Scanner(System.in);while (true) {System.out.println("请说:");String msg=sc.next();if("exit".equals( msg)){System.out.println("退出成功");dos.close();//关闭输出流socket.close();//关闭socketbreak;}dos.writeUTF(msg);dos.flush();//刷新管道}}
}
TCPdemoSe2类:
package com.item.Inter6demoTCP3;import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.sql.SQLOutput;
public class TCPdemoSe2 {public static void main(String[] args) throws IOException {//服务多收,支持多客户端开发System.out.println("==服务端启动==");//1.创建服务端对象,绑定端口号,监听客户端连接ServerSocket ss=new ServerSocket(8080);Socket socket= ss.accept();System.out.println("一个客户端上线:"+socket.getInetAddress().getHostAddress());while (true) {//2.等待客户端连接,调用accept方法,阻塞等待客户端连接,一旦有客户端连接,返回Socket对象socket = ss.accept();//3.把客户端管道交给一个独立的子线程专门负责接受这个管道的消息。new ServerReader(socket).start();}}
}
ServerReader类:(线程类)
package com.item.Inter6demoTCP3;import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
public class ServerReader extends Thread{public Socket socket;public ServerReader(Socket socket) {this.socket = socket;}@Overridepublic void run() {try {//4.获取输入流,读取数据InputStream is=socket.getInputStream();//5.把字节输入流包装成特殊数据输入流DataInputStream dis=new DataInputStream(is);while (true) {//6.读取数据String msg=dis.readUTF();System.out.println(",msg="+msg);//7.客户端的ip和端口System.out.println("客户端的ip和端口"+socket.getInetAddress().getHostAddress()+":"+socket.getPort());System.out.println("-------------------");}} catch (Exception e) {e.printStackTrace();System.out.println("客户端连接关闭");}}
}
4.BS架构的原理
http://服务器IP:端口号
- 注意:服务器必须给浏览器响应HTTP协议规定的数据格式,否则浏览器不识别返回的数据。
代码演示
TCPdemoSe2类:
package com.item.Inter7demoBS;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class TCPdemoSe2 {public static void main(String[] args) throws IOException {//目的BS架构的原理理解。System.out.println("==服务端启动==");//1.创建服务端对象,绑定端口号,监听客户端连接ServerSocket ss=new ServerSocket(8080);Socket socket= ss.accept();System.out.println("一个客户端上线:"+socket.getInetAddress().getHostAddress());while (true) {//2.等待客户端连接,调用accept方法,阻塞等待客户端连接,一旦有客户端连接,返回Socket对象socket = ss.accept();//3.把客户端管道交给一个独立的子线程专门负责接受这个管道的消息。new ServerReader(socket).start();}}
}
ServerReader类:
package com.item.Inter7demoBS;
import java.io.DataInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;
public class ServerReader extends Thread{public Socket socket;public ServerReader(Socket socket) {this.socket = socket;}@Overridepublic void run() {try {//给当前对应的浏览器管道响应一个网页数据回去。OutputStream os=socket.getOutputStream();//通过字节输出流包装写出去数据给浏览器//把字节输出流包装成打印流PrintStream ps=new PrintStream(os);//写响应的网页数据出去ps.println("HTTP/1.1 200 OK");//格式头ps.println("Content-Type:text/html;charset=utf-8");//文件 类型ps.println();//换一行ps.println("<html>");ps.println("<head>");ps.println("<meta charset='utf-8'/>");ps.println("<title>");ps.println("响应标题");ps.println("</title>");ps.println("</head>");ps.println("<body>");ps.println("<h1>");ps.println("响应内容");ps.println("</h1>");ps.println("</body>");ps.println("</html>");ps.close();socket.close();//启动以后,可以在自己的浏览器中访问:http://127.0.0.1:8080/} catch (Exception e) {e.printStackTrace();System.out.println("客户端连接关闭");}}
}
5.优化第4单元
引入线程池,不会造成线程浪费。
代码演示
TCPdemoSe2类:
package com.item.Inter8demoBS2;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.*;public class TCPdemoSe2 {public static void main(String[] args) throws Exception {//目的BS架构的原理理解。System.out.println("==服务端启动==");//1.创建服务端对象,绑定端口号,监听客户端连接ServerSocket ss=new ServerSocket(8080);Socket socket= ss.accept();System.out.println("一个客户端上线:"+socket.getInetAddress().getHostAddress());//创建线程池ExecutorService pool=new ThreadPoolExecutor(3,10,10, TimeUnit.SECONDS,new ArrayBlockingQueue<>(100),Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());while (true) {//2.等待客户端连接,调用accept方法,阻塞等待客户端连接,一旦有客户端连接,返回Socket对象socket = ss.accept();//3.把客户端管道包装成一个任务交给线程池处理pool.execute(new ServerReaderRunnable(socket));//线程对象也可以当成任务对象}}
}
ServerReaderRunnable类:
package com.item.Inter8demoBS2;import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;public class ServerReaderRunnable implements Runnable{public Socket socket;public ServerReaderRunnable(Socket socket) {this.socket = socket;}@Overridepublic void run() {try {//给当前对应的浏览器管道响应一个网页数据回去。OutputStream os=socket.getOutputStream();//通过字节输出流包装写出去数据给浏览器//把字节输出流包装成打印流PrintStream ps=new PrintStream(os);//写响应的网页数据出去ps.println("HTTP/1.1 200 OK");//格式头ps.println("Content-Type:text/html;charset=utf-8");//文件 类型ps.println();//换一行ps.println("<html>");ps.println("<head>");ps.println("<meta charset='utf-8'/>");ps.println("<title>");ps.println("响应标题");ps.println("</title>");ps.println("</head>");ps.println("<body>");ps.println("<h1>");ps.println("响应内容");ps.println("</h1>");ps.println("</body>");ps.println("</html>");ps.close();socket.close();//启动以后,可以在自己的浏览器中访问:http://127.0.0.1:8080/} catch (Exception e) {e.printStackTrace();System.out.println("客户端连接关闭");}}
}