网络编程
URL
url: 统一资源定位符
互联网的三大基石: html http url
URL 类 :
https://www.baidu.com
String getPath() 得到这个 URL路径的一部分。
String getHost() 这个 URL的主机名,如果适用的话。
int getPort() 这个 URL的端口号。
String getProtocol() 这个 URL的协议名称。
String getQuery() 获取查询 URL的一部分。
String getRef() 得到了锚(也称为“参考”) URL。
//简单爬虫
public class Demo01 {
public static void main(String[] args) throws IOException {
URL url=new URL("https://www.taobao.com");
System.out.println(url);
System.out.println("协议"+url.getProtocol());
System.out.println("端口"+url.getPort());
System.out.println("域名"+url.getHost());
System.out.println("查询内容"+url.getQuery());
System.out.println("锚点"+url.getRef());
//获取一个从url位置到程序的输入流
InputStream str=url.openStream();
//读取
byte[] car=new byte[1024];
int len=-1;
while((len=str.read(car))!=-1){
System.out.println(new String(car,0,len));
}
}
}
传输层协议:
- tcp:面向连接 3次握手 安全 开销大 效率低 大小没有限制
- udp:非面向连接 不安全 协议简单 开销小 效率高 只管写只管发 大小限制一般不超过60k
面向Socket编程
传输层为应用层开辟的口子,用来传出数据
UDP
UDP对socket实现
- DatagramPacket: 打包|数据报包
- DatagramPacket(byte[] buf, int offset, int length, SocketAddress address) 构造一个数据报包发送数据包的长度 length抵消 ioffsetto指定主机上的指定端口号。
- DatagramPacket(byte[] buf, int length) 构造一个 DatagramPacket length接收数据包的长度。
- DatagramSocket : 定义发送端或者接收端
- DatagramSocket(int port) 构造一个数据报套接字绑定到本地主机上的指定端口。
DatagramSocket(int port, InetAddress laddr) 创建数据报套接字,绑定到指定的本地地址。
UDP基本流程:
发送端
- 定义发送端DatagramSocket(int port)
- 准据数据
- 打包
- 发送void send(DatagramPacket p) 从这个套接字发送一个数据报包。
- 关闭
注意:统一协议下端口号不能冲突
public class UDPSend02{
public static void main(String[] args) throws IOException {
System.out.println("-------------发送端----------------");
//1.定义发送端DatagramSocket(int port)
DatagramSocket client=new DatagramSocket(6666);
//2.准据数据
byte[] arr="海贼王-->香克斯".getBytes();
//3.打包
DatagramPacket packet=new DatagramPacket(arr, 0, arr.length,new InetSocketAddress("localhost",9999));
//4.发送
client.send(packet);
//5.关闭
client.close();
}
}
接收端
- 定义接收端 DatagramSocket(int port)
- 打包用来接收数据
- 接收数据 receive(DatagramPacket p) 从这个套接字接收数据报包。
- 处理数据 byte[] getData() int getLength()
- 关闭
public class UDPReceive03 {
public static void main(String[] args) throws IOException {
System.out.println("-------------接收端----------------");
//1.定义接收端 DatagramSocket(int port)
DatagramSocket server=new DatagramSocket(9999);
//2.打包用来接收数据
byte[] arr=new byte[1024*60];
DatagramPacket packet=new DatagramPacket(arr, arr.length);
//3.接收数据 receive(DatagramPacket p) 从这个套接字接收数据报包。
server.receive(packet);
//4.处理数据
byte[] data=packet.getData();
int len=packet.getLength();
System.out.println(new String(data,0,len));
System.out.println(data.length);
System.out.println(len);
//5.关闭
server.close();
}
}
TCP
tcp基本流程:
客户端
- 1.定义客户端 Socket Socket(InetAddress address, int port) 创建一个流套接字连接到指定的端口号在指定的IP地址。
- 2.io操作 InputStream getInputStream() 返回此套接字的输入流。
- 3.关闭
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class TcpClient04 {
public static void main(String[] args) throws UnknownHostException, IOException {
System.out.println("------我是客户端-------");
//1.定义客户端
Socket client=new Socket("127.0.0.1",9999);
//2.IO操作
OutputStream os=client.getOutputStream();
os.write("今天是星期六".getBytes());
//3.刷出
os.flush();
//4.关闭
os.close();
client.close();
}
}
服务端
- 1.定义服务端 ServerSocket(int port) 创建一个服务器套接字绑定到指定端口。
- 2.阻塞式监听 accept()
- 3.io操作
- 4.数据的处理
- 5.关闭
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class TcpServer05 {
public static void main(String[] args) throws IOException {
System.out.println("------我是服务端-------");
//1.定义服务端 ServerSocket(int port) 创建一个服务器套接字绑定到指定端口。
ServerSocket server=new ServerSocket(9999);
//2.阻塞式监听 accept()
Socket socket=server.accept();
System.out.println("一个客户端连接成功了.....");
//3.io操作
InputStream is=socket.getInputStream();
byte[] arr=new byte[1024];
int len=is.read(arr);
//4.数据的处理
System.out.println(new String(arr,0,len));
//5.关闭
is.close();
socket.close();
server.close();
}
}
实现多用户登录
服务端
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Arrays;
public class LoginServer10 {
public static void main(String[] args) throws IOException {
System.out.println("------我是服务端-------");
//1.定义服务端
ServerSocket server=new ServerSocket(9999);
boolean flag=true;
while(flag){
//2.阻塞式监听 accept()
Socket socket=server.accept();
System.out.println("一个客户端连接成功了.....");
//3.io操作
new Thread(new Channel(socket)).start();
}
server.close(); //死循环后面的代码无法执行
}
//静态内部类 管道 对每一个登录的用户执行的流程
static class Channel implements Runnable{
Socket socket ;
InputStream is;
OutputStream os;
public Channel(Socket socket) {
this.socket=socket;
try {
is = socket.getInputStream();
os=socket.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
}
//读入
public String read(){
String str="";
byte[] arr=new byte[1024];
try {
int len=is.read(arr);
str=new String(arr,0,len);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return str;
}
//写出
public void write(String msg){
try {
os.write(msg.getBytes());
os.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
//4.数据的处理
String data=read();
//处理方式2
String uname="";
String pwd="";
String[] str=data.split("&");
for(String s:str){
System.out.println(s);
String[] ss=s.split("=");
System.out.println(Arrays.toString(ss));;
if(ss[0].equals("name")){
uname = ss[1];
}else if(ss[0].equals("pwd")){
pwd= ss[1];
}
}
//判断
if(uname.equals("zhangsan")&&pwd.equals("123")){
write("登录成功");
}else{
write("登录失败");
}
close();
}
//关闭
public void close(){
//5.关闭
try { //alt+shift+z 一段代码一起添加到一个异常中
if(os!=null){
os.close();
}
if(is!=null){
is.close();
}
if(socket!=null){
socket.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}