Java-网络编程

计算机网络是通过传输介质通信设施网络通信协议,把各种网络设备互相连接起来,实现资源共享和数据传输的系统。网络编程是实现互联网上的多个设备之间进行数据传输

网络协议

网络协议是用来规定数据传输的规则,为了统一网络传输的标准,国际标准化组织定义了OSI模型(开放系统互联参考模型),但由于OSI模型的协议比较复杂,所以并没有得到广泛的应用,而在实际应用中一般采用TCP/IP模型。

网络通信的要素

ip地址
端口号   
     端口分类:
        公有端口 0~1023
             HTTP : 80
             HTTPS : 443
             FTP : 21
             Telent : 23
        程序注册端口:1024~49151 分配用户或者程序
           tomcat:8080
           mysql:3306
           Orcal:1521
       动态、私有端口: 49152~65535

好比你要去某地找某个人,需要知道地址(具体到单元楼)和门牌号。

网络分层

在这里插入图片描述

TCP(Transmission COntrol Protocol)传输控制协议

TCP协议提供IP环境下数据可靠传输,通过面向连接、端对端和可靠的数据包进行传输。即它是事先为所发送的数据建立好连接通道,然后在进行数据发送。

三次握手

建立一个可靠的连接需要三次握手
在这里插入图片描述

三次握手过程说明:
第一次握手:Client发送标志位(位码) syn(建立联机)=1 随机产生序列号seq=100的数据发送给Server,Server收到syn=1则知道Client要求建立联机。
第二次握手:Server收到Client请求后确认联机信息,向Client发送ack(确认信号)=(Client的seqno+1),syn=1,随机产生序列号seqno=100的数据发送给Client。
第二次握手:Client收到ack后检查是否正确,若正确,Client再次发送ack=(Server的seq+1),Server确认后则表明连接成功。

举一个不怎么恰当的例子例:
   例如跑步比赛:将发送指令的作为客户端,参赛者为服务器
              则: 预备 是客户端发送给服务器的第一次握手
                      运动员准备好了的信息 是服务端发送给客户端的第二次握手信息
                      跑: 是客户端发送给服务器的第三次握手
四次挥手

TCP连接因为是全双工的,因此单方面断开连接是不够的。断开了发送,并不能保证不会进行接收,因此需要客户端和服务端双方都有断开连接的动作
在这里插入图片描述

第一次挥手:
当数据传输即将完成,Client向服务端发送Fin(结束信号)=1的请求关闭标志位,代表告诉Server,Client数据传输完成,准备关闭连接
第二次挥手:
Server收到FIN后,Server先发送一个ACK信号给Client,确认序号为收到的序列号+1,表达的意思为你方的请求关闭我方已收到,但我方还有数据传输未完成,待我传输完成再告诉你。
第三次挥手:
Server数据传输完成,向Client发送Fin=1,Client收到Server发送的Fin=1时,知道Server的数据传输完成,可以断开连接。
第四次挥手:Client收到Server发送的Fin=1后,向Server发送ack信号确认信息进行确认,同时把自身状态设置为time_wait状态,启动计时器。如果Server没有收到Clent发送的ack,则在计时器结束后会要求客户端再发送一次ack,当Server收到Client的ack后,Server断开连接。Client在2MLS(2倍报文最大生存时间)后没有收到Server发送的重传ack请求,则认为服务端已接收到了客户端的ack,Client断开连接。

举一个不怎么恰当的例子例:
   例如男女朋友吵架:
              则: 女:我们分手吧     是客户端发送给服务器的第一次挥手信息
                      男:嗯 好吧!   是服务端发送给客户端的第二次挥手信息
                      男:那我们分手吧   是服务端发送给客户端的第三次挥手信息
                      女: 嗯 再见!  是客户端发送给服务器的第四次挥手信息

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

UDP协议全称是用户数据报协议,在网络中它与TCP协议一样用于处理数据包,是一种无连接的协议。

TCP和UDP比较
UDPTCP
是否连接无连接面向连接
是否可靠不可靠可靠
连接对象个数支持一对一、一对多、多对多和多对一交互通信只能一对一通信
传输方式面向报文面向字节流
使用场景使用与实时应用(IP电话、视频会议、直播等)适用于要求可靠传输的应用。例如文件传输
Java网络编程

java.net包中包含的类和接口,提供了低层次的通信细节

InetAddress 类的方法

此类表示Internet协议(IP)地址。
IP地址是由IP使用的32位或128位无符号数字,构建UDP和TCP协议的低级协议。

import java.net.InetAddress;
import java.net.UnknownHostException;

public class InetAddressTest {

    public static void main(String[] args) {
        try {
            //查询本机ip地址
            InetAddress local_ip = InetAddress.getByName("localhost");
            System.out.println(local_ip);
            local_ip = InetAddress.getByName("127.0.0.1");
            System.out.println(local_ip);
            System.out.println(InetAddress.getByName("liang-PC"));
            System.out.println(InetAddress.getLocalHost());

            InetAddress baidu_ip = InetAddress.getByName("www.baidu.com");//查询网站ip地址
            System.out.println(baidu_ip);
            System.out.println(baidu_ip.getAddress());//InetAddress对象的原始IP地址
            System.out.println(baidu_ip.getHostName());//获取此IP地址的主机名。
            System.out.println(baidu_ip.getHostAddress());//返回文本显示中的IP地址字符串。
            System.out.println(baidu_ip.getCanonicalHostName());//获取此IP地址的完全限定域名。

        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
    }
}
InetSocketAddress类的方法

该类实现IP套接字地址(IP地址+端口号)它也可以是一对(主机名+端口号)

import java.net.InetSocketAddress;

public class InetSocketAddressTest {

    public static void main(String[] args) {
        //该类实现IP套接字地址(IP地址+端口号)它也可以是一对(主机名+端口号),在这种情况下将尝试解析主机名。
        InetSocketAddress inetSocket = new InetSocketAddress("127.0.0.1", 8080);
        System.out.println(inetSocket);

        System.out.println(inetSocket.getAddress());//获得 InetAddress
        System.out.println(inetSocket.getHostName());//
        System.out.println(inetSocket.getHostString());//地址
        System.out.println(inetSocket.getPort());//端口
    }
}

TCP简单通信

服务器端
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * @deprecated : 服务器端
 * @author liang
 */
public class TcpServerDemo {

    public static void main(String[] args) {
        ServerSocket serverSocket = null;//服务器套接字
        Socket socket = null;
        InputStream inputStream = null;
        try {
            serverSocket = new ServerSocket(8888);//创建绑定到指定端口的服务器套接字
            socket = serverSocket.accept();//侦听要连接到此套接字并接受它。 该方法将阻塞直到建立连接。
            inputStream = socket.getInputStream();//获取该套接字的输入流
            //接收流数据
            byte[] bytes = new byte[1024];
            int len = 0;
            while ((len = inputStream.read(bytes)) != -1){
                String str = new String(bytes,0,len);
                System.out.println(str);
            }

        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //关闭流
            if (inputStream!=null){
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            //关闭套接字
            if (socket != null){
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            //关闭服务器套接字
            if (serverSocket != null){
                try {
                    serverSocket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }
    }

}
客户端
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
/**
 * @deprecated : 客户端
 * @author liang
 */
public class TcpClientDemo {

    public static void main(String[] args) {
        Socket client = null;
        OutputStream outputStream = null;

        try {
            InetAddress inetAddress = InetAddress.getByName("127.0.0.1");
            int port =8888;
            //创建流套接字并将其连接到指定IP地址的指定端口号
            client = new Socket(inetAddress,port);
            //获取该套接字的输出流
            outputStream = client.getOutputStream();
            //创建Scanner套接字
            Scanner scanner = new Scanner(System.in);
            while (scanner.hasNextLine()){
                String line = scanner.nextLine();//获取输入行数据
                //将数据写入输出流
                outputStream.write(line.getBytes(),0,line.getBytes().length);
            }
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //关闭输出流
            if (outputStream!=null){
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            //关闭客户端套接字
            if (client!=null){
                try {
                    client.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }

}

TCP简单通信 — 文件上传

文件服务器
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class FileServer {

    public static void main(String[] args) {
        ServerSocket serverSocket = null;//服务器套接字
        Socket socket = null;//套接字
        InputStream inputStream = null;//输入流
        FileOutputStream fileOutputStream = null;//文件输出流
        OutputStream outputStream = null;//输出流
        try {
            serverSocket = new ServerSocket(8888);//创建绑定到指定端口的服务器套接字
            socket = serverSocket.accept();//侦听要连接到此套接字并接受它。 该方法将阻塞直到建立连接。
            inputStream = socket.getInputStream();//获取该套接字的输入流
            fileOutputStream = new FileOutputStream(new File("rec.jpg"));//创建文件输出流
            //读取输入流数据 并写入文件输出流
            byte[] buff = new byte[1024];
            int len = 0;
            while ((len = inputStream.read(buff)) != -1){
                fileOutputStream.write(buff,0,len);
            }

            //获取该套接字的输出流
            outputStream = socket.getOutputStream();
            outputStream.write("接收完毕,可以断开了".getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (outputStream != null){
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fileOutputStream != null){
                try {
                    fileOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (inputStream != null){
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (socket != null){
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (serverSocket != null){
                try {
                    serverSocket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }

}
文件客户端
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;

public class FileClient {

    public static void main(String[] args) {
        Socket socket = null;
        FileInputStream fileInputStream = null;
        OutputStream outputStream = null;
        InputStream inputStream = null;
        try {
            InetAddress inetAddress = InetAddress.getByName("127.0.0.1");
            int port = 8888;
            socket = new Socket(inetAddress,port);//创建流套接字并将其连接到指定IP地址的指定端口号
            outputStream = socket.getOutputStream();//获取该套接字的输出流
            fileInputStream = new FileInputStream(new File("Hydrangeas.jpg"));//创建文件输入流

            //读取文件输入流数据,并写入输出流
            byte[] buff = new byte[1024];
            int len = 0;
            while ((len = fileInputStream.read(buff)) != -1){
                outputStream.write(buff,0,len);
            }
            /*
             在客户端或者服务端通过socket.shutdownOutput()都是单向关闭的,即关闭客户端的输出流并不会关闭服务端的输出流,所以是一种单方向的关闭流;
             通过socket.shutdownOutput()关闭输出流,但socket仍然是连接状态,连接并未关闭
             如果直接关闭输入或者输出流,即:in.close()或者out.close(),会直接关闭socket
             */
            //通知服务器 我数据输出完毕
            socket.shutdownOutput();//关闭客户端输出流
            //获取该套接字的输入流
            inputStream = socket.getInputStream();
            len = 0;
            //接收并打印输入流数据
            while ((len = inputStream.read(buff)) != -1){
                String str = new String(buff,0,len);
                System.out.println(str);
            }
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (inputStream != null){
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fileInputStream != null){
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (outputStream != null){
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (socket != null){
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }
}

UDP简单通信

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;

public class UdpSocket1 {
    public static void main(String[] args) {
        DatagramSocket datagramSocket = null;
        try {
            //DatagramSocket表示用于发送和接收数据报数据包的套接字。
             datagramSocket = new DatagramSocket(8888);
            String str = "我是UDP传输端1";
            //DatagramPacket表示数据报包,数据报包用于实现无连接分组传送服务。
            DatagramPacket datagramPacket = new DatagramPacket(str.getBytes(),0,str.getBytes().length, InetAddress.getByName("127.0.0.1"),9999);
            datagramSocket.send(datagramPacket);
            
        } catch (SocketException e) {
            e.printStackTrace();
        } catch (IOException e) {
        e.printStackTrace();
        }finally {
            if (datagramSocket != null){
                datagramSocket.close();
            }
        }
    }
}
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

public class UdpSocket2 {

    public static void main(String[] args) {
        DatagramSocket datagramSocket = null;
        try {
            //创建数据报套接字
            datagramSocket = new DatagramSocket(9999);
            //接收数据包
            byte[] buff = new byte[1024];
            DatagramPacket datagramPacket = new DatagramPacket(buff,0,buff.length);
            datagramSocket.receive(datagramPacket);//阻塞式接收

            System.out.println(datagramPacket.getAddress());
            System.out.println(datagramPacket.getPort());
            System.out.println(new String(datagramPacket.getData(),0,datagramPacket.getLength() ));

        } catch (SocketException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (datagramSocket != null){
                datagramSocket.close();
            }
        }

    }
}

UDP简单通信 — 聊天

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

public class TalkSend implements Runnable {
    int partFrom = 0;//接收端 端口
    int partTo = 0;//发送到 端口
    String ipTo = null;//发送到ip

    public TalkSend(int partFrom,int partTo, String ipTo){
        this.ipTo = ipTo;
        this.partFrom = partFrom;
        this.partTo = partTo;
    }

    @Override
    public void run() {
        DatagramSocket datagramSocket = null;
        try {

            //DatagramSocket表示用于发送和接收数据报数据包的套接字。
            datagramSocket = new DatagramSocket(partFrom);
            Scanner scanner = new Scanner(System.in);

            while (scanner.hasNextLine()){
                String line = scanner.nextLine();
                DatagramPacket datagramPacket = new DatagramPacket(line.getBytes(),0,line.getBytes().length, InetAddress.getByName(ipTo),partTo);
                datagramSocket.send(datagramPacket);
            }
        } catch (SocketException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (datagramSocket != null){
                datagramSocket.close();
            }
        }
    }

}
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

public class TalkRec implements Runnable {

    int partFrom = 0;//接收端 端口


    public TalkRec(int partFrom){
        this.partFrom = partFrom;
    }

    @Override
    public void run() {
        DatagramSocket datagramSocket = null;
        try {
            //创建数据报套接字
            datagramSocket = new DatagramSocket(partFrom);
            while (true) {
                //接收数据包
                byte[] buff = new byte[1024];
                DatagramPacket datagramPacket = new DatagramPacket(buff, 0, buff.length);
                datagramSocket.receive(datagramPacket);//阻塞式接收
                System.out.println(datagramPacket.getAddress()+":"+datagramPacket.getPort()+" : "+new String(datagramPacket.getData(), 0, datagramPacket.getLength()));
            }
        } catch (SocketException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (datagramSocket != null){
                datagramSocket.close();
            }
        }
    }
}
public class Talk1 {

    public static void main(String[] args) {

        new Thread(new TalkSend(7777,9999,"127.0.0.1")).start();
        new Thread(new TalkRec(8888)).start();

    }
}

public class Talk2 {
    public static void main(String[] args) {

        new Thread(new TalkSend(5555,8888,"127.0.0.1")).start();
        new Thread(new TalkRec(9999)).start();
    }
}

URL 统一资源定位符

用于定位资源。在WWW上,每一信息资源都有统一的且在网上唯一的地址,该地址就叫URL(Uniform Resource Locator,统一资源定位器),它是WWW的统一资源定位标志,就是指网络地址。

URL组成
协议://主机:端口/项目名/资源文件名
import java.net.MalformedURLException;
import java.net.URL;

public class URLTest {
    public static void main(String[] args) {
        try {
            URL url = new URL("https://editor.csdn.net/md?articleId=110088434");

            System.out.println(url.getPath());//文件名
            System.out.println(url.getHost());//主机名
            System.out.println(url.getProtocol());//协议
            System.out.println(url.getFile());//全路径
            System.out.println(url.getQuery());//参数 键值对
            System.out.println(url.getPort());//端口号

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

    }
}
URL下载网络资源
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;

public class UrlDownload {
    public static void main(String[] args) {
        InputStream in = null;
        FileOutputStream fileOutputStream = null;
        try {
            URL url = new URL("https://m701.music.126.net/20201125215637/9b70b42b383bf399d5a7d3f2aee8b941/jdyyaac/obj/w5rDlsOJwrLDjj7CmsOj/4903215562/5bfc/fbd2/fa38/adfd6bf3d0fb529fb2681943d6065842.m4a");
            URLConnection urlConnection = url.openConnection();
            in = urlConnection.getInputStream();
            fileOutputStream = new FileOutputStream(new File("5842.m4a"));
            byte[] buff = new byte[1024];
            int len = 0;
            while ((len = in.read(buff)) != -1){
                fileOutputStream.write(buff,0,len);
            }

        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (fileOutputStream != null){
                try {
                    fileOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (in != null){
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }


    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值