127.0.0.1 本地IP
localhost 本地 域名
ip->域名 DNS服务器
InetAddress 此类表示互联网协议 (IP) 地址。
InetAddress in1=InetAddress.getLocalHost();
System.out.println(in1); //AB-201905250842/192.168.3.246
System.out.println(in1.getHostName()); //AB-201905250842 主机名
System.out.println(in1.getHostAddress()); //192.168.3.246
//static InetAddress getByName(String host) 在给定主机名的情况下确定主机的 IP 地址。
InetAddress in2=InetAddress.getByName("www.baidu.com");
System.out.println(in2); //www.baidu.com/123.56.138.186
System.out.println(in2.getHostName()); //www.baidu.com
System.out.println(in2.getHostAddress()); //123.56.138.186
端口:
1.区分软件
2.2个字节 0~65535之间的整数 udp tcp
3.统一协议下端口号不能冲突
4.建议使用8000以上自定义端口号
常见的端口号:
http : 80
tomcat : 8080
oracle : 1521
mysql : 3306
InetSocketAddress 此类实现 IP 套接字地址(IP 地址 + 端口号)。
构造方法摘要
InetSocketAddress(InetAddress addr, int port)
根据 IP 地址和端口号创建套接字地址。
InetSocketAddress(int port)
创建套接字地址,其中 IP 地址为通配符地址,端口号为指定值。
InetSocketAddress(String hostname, int port)
根据主机名和端口号创建套接字地址。
常用方法:
InetAddress getAddress()
获取 InetAddress。
String getHostName()
获取 hostname。
int getPort()
获取端口号。
//InetSocketAddress(String hostname, int port)
InetSocketAddress add=new InetSocketAddress("localhost", 8888);
System.out.println(add); //localhost/127.0.0.1:8888
System.out.println(add.getHostName());
System.out.println(add.getAddress());
System.out.println(add.getPort());
URL 统一资源定位符 定位网络上的资源
互联网的三大基石 : http html url
包含: http://www.baidu.com:80/index.html?uname=zhangsan&upwd=123#a
协议:http
域名:www.baidu.com
端口:80
资源:index.html?uname=zhangsan&upwd=123#a
URL 类 类 URL 代表一个统一资源定位符,它是指向互联网“资源”的指针。
//URL(String spec) 根据 String 表示形式创建 URL 对象
URL url =new URL("http://www.baidu.com:80/index.html?uname=zhangsan&upwd=123#a");
System.out.println(url);
//常用方法:
System.out.println("协议:"+ url.getProtocol());
System.out.println("域名:"+ url.getHost());
System.out.println("端口:"+ url.getPort());
System.out.println("资源:"+ url.getFile());
System.out.println("查询数据:"+ url.getQuery());
System.out.println("路径:"+ url.getPath());
System.out.println("锚点:"+ url.getRef());
爬虫
public class SpiderDemo04 {
public static void main(String[] args) throws IOException {
URL url=new URL("https://www.mi.com");
//InputStream openStream() 打开到此 URL 的连接并返回一个用于从该连接读入的 InputStream。
InputStream is=url.openStream();
//想要一行一行的读取多个字符的内容
BufferedReader read=new BufferedReader(new InputStreamReader(is));
BufferedWriter write=new BufferedWriter(new FileWriter("src/haha.html"));
//循环读取多行
String msg=null;
System.out.println(read.readLine());
while((msg=read.readLine())!=null){
write.write(msg);
System.out.println(write);
}
//刷出
write.flush();
//关闭
write.close();
read.close();
is.close();
}
}
资源传输协议:
- udp: 写信 非面向连接 只管写只管丢 协议简单,开销小,效率高 不安全 大小有限制,最好不要超过60k
- tcp: 打电话 面向连接 安全 效率低 基于3次握手: 1.你好,发送请求 2.我在,回应,连接已经构建 3.发送数据
Socket 套接字
socket就是传输层为应用层开辟的小口子,通过这个socket进行发送|接收数据
不同的协议对于socket的实现不一样
UDP实现Socket编程
DatagramSocket 定义发送端,接收端
DatagramPacket 数据报包 为数据进行打包
udp基本流程: 发送端
1.定义发送端 DatagramSocket(端口) 发送端端口
2.准备一个字节数组进行打包,用来接收数据
3.接收
4.处理数据
5.关闭
1.定义接收端 DatagramSocket(端口)
2.准备一个字节数组进行打包,用来接收数据
3.接收
4.处理数据
5.关闭
public class UDPSent01 {
public static void main(String[] args) throws IOException {
System.out.println("-----------发送端--------------");
//1.定义发送端 DatagramSocket(端口)
DatagramSocket send=new DatagramSocket(8888);
//2.准备数据+打包DatagramPacket(byte[] buf, int length, InetAddress address, int port) 构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。
String str="你好呀";
byte[] arr=str.getBytes();
DatagramPacket packet=new DatagramPacket(arr,arr.length,InetAddress.getLocalHost(),9999);
//3.发送
send.send(packet);
//4.关闭
send.close();
}
}
public class UDPReceive02 {
public static void main(String[] args) throws IOException {
System.out.println("-----------接收端--------------");
//1.定义接收端 DatagramSocket(端口)
DatagramSocket receive=new DatagramSocket(9999);
//2.准备字节数组进行打包
byte[] arr=new byte[1024*60];
//DatagramPacket(byte[] buf, int length) 构造 DatagramPacket,用来接收长度为 length 的数据包。
DatagramPacket packet=new DatagramPacket(arr,arr.length);
//3.接收
receive.receive(packet);
/*
* 4.处理数据
* byte[] getData() 返回数据缓冲区。
int getLength() 返回将要发送或接收到的数据的长度。
*/
byte[] datas=packet.getData();
int len=packet.getLength();
System.out.println(new String(datas,0,len).length());
System.out.println(new String(arr).length());
//5.关闭
receive.close();
}
}
udp传输文件流程: 发送端
1.定义发送端 DatagramSocket(端口) 发送端端口
2.数据从本地读到程序,转为字节数组的形式
3.打包
4.发送 send
5.关闭
1.定义接收端 DatagramSocket(端口)
2.准备一个字节数组进行打包,用来接收数据
3.接收
4.准备输出流,写出到文件
5.关闭
public class FileUDPSent03 {
public static void main(String[] args) throws IOException {
System.out.println("-----------发送端--------------");
//1.定义发送端 DatagramSocket(端口)
DatagramSocket send=new DatagramSocket(8888);
//2.准备数据+打包DatagramPacket(byte[] buf, int length, InetAddress address, int port) 构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。
InputStream is=new BufferedInputStream(new FileInputStream("D:/haha.txt"));
byte[] car=new byte[3];
int len=-1;
while((len=is.read(car))!=-1){
DatagramPacket packet=new DatagramPacket(car,len,InetAddress.getLocalHost(),9999);
//3.发送
send.send(packet);
}
//循环结束文件中的内容全部写出去了
byte[] bytes="再见".getBytes();
send.send(new DatagramPacket(bytes,bytes.length,InetAddress.getLocalHost(),9999));
//4.关闭
is.close();
send.close();
}
}
public class FileUDPReceive04 {
public static void main(String[] args) throws IOException {
System.out.println("-----------接收端--------------");
//1.定义接收端 DatagramSocket(端口)
DatagramSocket receive=new DatagramSocket(9999);
//2.准备字节数组进行打包
byte[] arr=new byte[1024*60];
//DatagramPacket(byte[] buf, int length) 构造 DatagramPacket,用来接收长度为 length 的数据包。
DatagramPacket packet=new DatagramPacket(arr,arr.length);
//输出流
OutputStream os=new BufferedOutputStream(new FileOutputStream("E:/haha.txt"));
//3.接收
while(true){
receive.receive(packet);
/*
* 4.处理数据
* byte[] getData() 返回数据缓冲区。
int getLength() 返回将要发送或接收到的数据的长度。
*/
byte[] datas=packet.getData();
int len=packet.getLength();
System.out.println(new String(datas,0,len));
if("再见".equals(new String(datas,0,len))){
System.out.println("--------");
break;
}else{
System.out.println("===========");
os.write(datas, 0, len);
}
}
os.flush();
//5.关闭
os.close();
receive.close();
}
}
UDP 基于字节数组传输
TCP 基于IO流传输
tcp实现客户端基本流程:
1.定义客户端 Socket Socket(String host, int port) 创建一个流套接字并将其连接到指定主机上的指定端口号。
2.io操作
3.关闭
tcp实现服务端开发:
1.定义服务端 ServerSocket(int port) 创建绑定到特定端口的服务器套接字。
2.阻塞式监听 Socket accept() 侦听并接受到此套接字的连接。
3.io操作
4.关闭
public class TCPClient01 {
public static void main(String[] args) throws UnknownHostException, IOException {
System.out.println("--------client----------");
//1.定义客户端 Socket
Socket client=new Socket("127.0.0.1", 7788); //ip ->服务器的ip 端口:服务端的端口号
//2.io
//获取输出流 OutputStream getOutputStream() 返回此套接字的输出流。
DataOutputStream os=new DataOutputStream(client.getOutputStream());
os.writeUTF("哈哈哈");
os.flush();
//3.关闭
os.close();
client.close();
}
}
public class TCPServer02 {
public static void main(String[] args) throws IOException {
System.out.println("--------server----------");
//1.定义服务端
ServerSocket server=new ServerSocket(7788);
//2.阻塞式监听 Socket accept()
Socket client=server.accept();
//3.io操作
//输入流
DataInputStream is=new DataInputStream(client.getInputStream());
System.out.println(is.readUTF());
//4.关闭
is.close();
}
}
tcp实现单项登录基本流程:
1.定义客户端 Socket Socket(String host, int port) 创建一个流套接字并将其连接到指定主机上的指定端口号。
2.接收到用户输入的数据,io发送到服务端
3.关闭
tcp实现单项登录服务端开发:
1.定义服务端 ServerSocket(int port) 创建绑定到特定端口的服务器套接字。
2.阻塞式监听 Socket accept() 侦听并接受到此套接字的连接。
3.io操作
4.处理数据(校验->结果打印到控制台)
5.关闭
public class LoginClient03 {
public static void main(String[] args) throws UnknownHostException, IOException {
System.out.println("--------client----------");
//1.定义客户端 Socket
Socket client=new Socket("127.0.0.1", 7788); //ip ->服务器的ip 端口:服务端的端口号
//2.io
//获取输出流 OutputStream getOutputStream() 返回此套接字的输出流。
DataOutputStream os=new DataOutputStream(client.getOutputStream());
//数据
String msg="name=zhangsan&pwd=1234";
os.writeUTF(msg);
os.flush();
//3.关闭
os.close();
client.close();
}
}
public class LoginServer04 {
public static void main(String[] args) throws IOException {
System.out.println("--------server----------");
//1.定义服务端
ServerSocket server=new ServerSocket(7788);
//2.阻塞式监听 Socket accept()
Socket client=server.accept();
//3.io操作
//输入流
DataInputStream is=new DataInputStream(client.getInputStream());
String str=is.readUTF();//"name=张三&pwd=123"
System.out.println(str);
//检验 name=zhangsan, pwd=1234
String[] strs=str.split("&");
String name="";
String pwd="";
for(String s:strs){
String[] arr=s.split("=");
if("name".equals(arr[0])){
name=arr[1];
}else if("pwd".equals(arr[0])){
pwd=arr[1];
}
}
if("laopei".equals(name) && "1234".equals(pwd)){
System.out.println("登录成功");
}else{
System.out.println("用户名或者密码失败");
}
//4.关闭
is.close();
}
}
tcp实现双项登录基本流程:
public class LoginTwoWayClient01 {
public static void main(String[] args) throws UnknownHostException, IOException {
System.out.println("--------client----------");
//1.定义客户端 Socket
Socket client=new Socket("127.0.0.1", 7788); //ip ->服务器的ip 端口:服务端的端口号
//键盘输入数据
BufferedReader input=new BufferedReader(new InputStreamReader(System.in));
System.out.println("请输入用户名");
//name=haha&pwd=12345
String name=input.readLine();
System.out.println("请输入密码:");
String pwd=input.readLine();
System.out.println(name+"-->"+pwd);
//2.io
//获取输出流 OutputStream getOutputStream() 返回此套接字的输出流。
DataOutputStream os=new DataOutputStream(client.getOutputStream());
DataInputStream is=new DataInputStream(client.getInputStream());
//数据
// String msg="name=laopei&pwd=1234";
os.writeUTF("name="+name+"&pwd="+pwd);
os.flush();
//读取相应数据
String str=is.readUTF();
System.out.println(str);
is.close();
//3.关闭
os.close();
client.close();
}
}
tcp实现双项登录服务端开发:
public class LoginTwoWayServer02{
public static void main(String[] args) throws IOException {
System.out.println("--------server----------");
//1.定义服务端
ServerSocket server=new ServerSocket(7788);
//2.阻塞式监听 Socket accept()
boolean isrunning=true;
while(isrunning){
Socket client=server.accept();
System.out.println("一个客户端连接成功....");
//3.io操作
//输入流
DataInputStream is=new DataInputStream(client.getInputStream());
String msg=is.readUTF();
//分析数据
String name="";
String pwd="";
String[] arr=msg.split("&");
for(String s:arr){
String[] ss=s.split("=");
if("name".equals(ss[0])){
name=ss[1];
}
if("pwd".equals(ss[0])){
pwd=ss[1];
}
}
//输出流
DataOutputStream out=new DataOutputStream(client.getOutputStream());
//判断是否登录成功
if(name.equals("laopei") & pwd.equals("1234")){
out.writeUTF("登录成功");
}else{
out.writeUTF("用户名或者密码错误");
}
out.flush();
//4.关闭
out.close();
is.close();
client.close();
}
server.close();
}
}
tcp实现多客户端登录服务端开发:
服务端可以相应多个客户端,但是如果使用循环,每个客户端是排队连接,没有办法达到同时执行,
如果想要服务端可以对多个客户端同时相应,可以选择使用多线程,一个客户端就是执行一遍处理相应的流程就是一个线程
public class LoginMulServer03{
public static void main(String[] args) throws IOException {
System.out.println("--------server----------");
//1.定义服务端
ServerSocket server=new ServerSocket(7788);
//2.阻塞式监听 Socket accept()
boolean isrunning=true;
while(isrunning){
Socket client=server.accept();
System.out.println("一个客户端连接成功....");
new Thread(new Channel(client)).start();
}
server.close();
}
static class Channel implements Runnable{
Socket client=null;
DataInputStream is=null;
DataOutputStream out=null;
public Channel(Socket client) {
this.client=client;
try {
is=new DataInputStream(client.getInputStream());
out=new DataOutputStream(client.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
//读入
public String read(){
String msg="";
try {
msg=is.readUTF();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return msg;
}
//写出
public void write(String str){
try {
out.writeUTF(str);
out.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
//关闭
public void close(){
try {
if(out!=null){
out.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
if(is!=null){
is.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
if(client!=null){
client.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void run() {
//分析数据
String name="";
String pwd="";
String[] arr=read().split("&");
for(String s:arr){
String[] ss=s.split("=");
if("name".equals(ss[0])){
name=ss[1];
}
if("pwd".equals(ss[0])){
pwd=ss[1];
}
}
//判断是否登录成功
if(name.equals("laopei") & pwd.equals("1234")){
write("登录成功");
}else{
write("用户名或者密码错误");
}
//4.关闭
close();
}
}
}