JavaOnline
网络编程 TCP/IP C/S
1.1、概述
目的
无线电台。传播交流信息,数据交换。通信
1、如何确保准确定位网络上的一台主机,端口。定位到这个计算机上的某个资源
2、找到了这个主机,如何传输数据?
1.2、网络通信的要素
如何实现网络通信?
通信双方的地址:
- ip
- 端口
 规则:网络通信的协议
 HTTP TCP IP UDP......
 小结:
 1、主要问题
- 如何准确的定位到网络上的一台或者多台主机
- 找到主机之后如何进行通信
 2、网络编程中的要素
- IP和端口号
- 网络通信协议UDP TCP
 3、万物皆对象
1.3、IP
IP地址:inetAddress
- 唯一定位一台网络上的计算机
- 127.0.0.1(4个字节组成 0-255 42亿):本机localhost
- ip地址的分类 ipv4(0-255)/ipv6(128位,8个无符号整数)
- 公网(互联网)-私网(局域网,192.168.xx.xx)
- 域名:记忆IP问题
应用
public class TestInetAddress {
    public static void main(String[] args) {
        try {
            //查询本机地址
            InetAddress inet1 = InetAddress.getByName("127.0.0.1");
            System.out.println(inet1);
            InetAddress inet2 = InetAddress.getByName("localhost");
            System.out.println(inet2);
            InetAddress inetAddresses = InetAddress.getLocalHost();
            System.out.println(inetAddresses);
            //查询网站IP地址
            InetAddress inet4 = InetAddress.getByName("www.baidu.com");
            System.out.println(inet4);
            //常用方法
            System.out.println(inet4.getAddress());
            System.out.println(inet4.getHostAddress());
            System.out.println(inet4.getCanonicalHostName());;
            System.out.println(inet4.getHostName());
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
    }
}
/127.0.0.1
localhost/127.0.0.1
DESKTOP-1M52ISN/192.168.119.1
www.baidu.com/110.242.68.3
[B@1b6d3586
110.242.68.3
110.242.68.3
www.baidu.com
Process finished with exit code 0
1.4、端口
端口表示计算机上一个程序的进程。
- 不同的进程有不同的端口号!用来区分软件!
- 端口被规定为0-65535
- TCP UDP :65535*2
- TCP:80,UDP:80?,单个协议下端口不能冲突
- 端口分类 公有端口0-1023.
- HTTP:80
- HTTPS:443
- FTP:21
- Telent:23
- 程序注册端口:1024-49151,分配用户或者程序
- Tomcat:8080
- MySQL:3306
- Oracle:1521
- 动态,私有:49152-65535
netstat -ano #查看所有端口
netstat -ano | findstr "5900" #查看指定端口
tasklist | findstr "8696" #
public class TestInetSocketAddress {
    public static void main(String[] args) {
        InetSocketAddress inetSocketAddress1 = new InetSocketAddress("127.0.0.1", 8080);
        InetSocketAddress inetSocketAddress = new InetSocketAddress("localhost", 8080);
        System.out.println(inetSocketAddress);
        System.out.println(inetSocketAddress1);
        System.out.println(inetSocketAddress1.getHostName());//地址
        System.out.println(inetSocketAddress1.getPort());//端口
        System.out.println(inetSocketAddress1.getAddress());
    }
}
localhost/127.0.0.1:8080
/127.0.0.1:8080
127.0.0.1
8080
127.0.0.1/127.0.0.1
1.5、通信协议
速率,传输码率,代码结构,传输控制....
TCP/IP协议簇
TCP:用户传输协议
UDP:用户数据报协议
IP:网络互联协议
TCP UDP对比
TCP:打电话
链接,稳定。
三次握手 四次挥手
三次握手
A:?
B:?
A:!
四次挥手
A:断开
B:我知道了
B:真的断开吗
A:断开 
客户端、服务端
传输完成,释放连接,效率低
UDP:发短信
不链接,不稳定
客户端,服务端:没有明确的界限
不管有没有准备好,都可以发给你
导弹
DDOS:洪水攻击(饱和攻击)
1.6、TCP
客户端
1、链接服务器Socket
2、发送消息
public class TcpClientDemo01 {
    public static void main(String[] args) {
        Socket socket = null;
        OutputStream os = null;
        try {
            //1、要知道服务器的地址和端口号
            InetAddress serverIP = InetAddress.getByName("127.0.0.1");
            int port = 9990;
            //2、创建一个Socket链接
            socket = new Socket(serverIP,port);
            //3、发送消息 IO源
            os = socket.getOutputStream();
            os.write("你好!!".getBytes());
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if (os != null){
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (socket!=null){
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
服务器
1、建立服务的端口 ServerSocket
2、等待用户的连接 accept
3、接受用的消息
public class TcpServerDemo01 {
    public static void main(String[] args) {
        ServerSocket serverSocket = null;
        Socket socket = null;
        InputStream is =null;
        ByteArrayOutputStream baos = null;
        try {
            //1、我要有一个地址
            serverSocket = new ServerSocket(9990);
            while (true){//一直接受客户端发送的消息
                //2、等待客户端链接过来
                socket = serverSocket.accept();
                //3、读取客户端的消息
                is = socket.getInputStream();
                //管道流
                baos = new ByteArrayOutputStream();
                byte[] buffer =new byte[1024];
                int len;
                while ((len=is.read(buffer))!=-1){
                    baos.write(buffer,0,len);
                }
                System.out.println(baos.toString());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (baos!=null){
                try {
                    baos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (is!=null){
                try {
                    is.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();
                }
            }
        }
    }
}
文件上传
客户端
public class TcpClientDemo02 {
    public static void main(String[] args) throws Exception {
        //1、创建一个Socket链接
        Socket socket = new Socket(InetAddress.getByName("127.0.0.1"),9990);
        //2、创建一个输出流
        OutputStream os = socket.getOutputStream();
        //3、读入文件
        FileInputStream fis = new FileInputStream(new File("aa.jpg"));
        //4、写出文件
        byte[] buffer = new byte[1024];
        int len;
        while ((len = fis.read(buffer))!=-1){
            os.write(buffer,0,len);
        }
        //通知服务器我结束了
        socket.shutdownOutput();//我已经传输完了
        //确定服务器接收完毕才能退出
        InputStream inputStream = socket.getInputStream();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        byte[] buffer2 = new byte[1024];
        int len2;
        while ((len2=inputStream.read(buffer2))!=-1){
            baos.write(buffer2,0,len2);
        }
        System.out.println(baos.toString());
        fis.close();
        os.close();
        socket.close();
    }
}
服务器端
public class TcpServerDemo02 {
    public static void main(String[] args) throws Exception {
        //1、创建服务
        ServerSocket serverSocket = new ServerSocket(9990);
        //2、阻塞式监听客户端的链接
        Socket socket =  serverSocket.accept();
        //3、获取输入流
        InputStream is = socket.getInputStream();
        //4、文件输出
        FileOutputStream fos = new FileOutputStream(new File("bb.jpg"));
        byte[] buffer = new byte[1024];
        int len;
        while ((len = is.read(buffer))!=-1){
            fos.write(buffer,0,len);
        }
        //通知客户端接收完毕
        OutputStream os = socket.getOutputStream();
        os.write("我已经接收完毕".getBytes());
        fos.close();
        is.close();
        socket.close();
        serverSocket.close();
    }
}
java中可以开端口号,此时若要打开电脑上一个相同端口号的应用则会报错(端口号被占用)
1.7、UDP
发送消息
发短信:不用链接,只需要知道对方的地址
A端
public class UdpClientDemo01 {
    public static void main(String[] args) throws Exception {
        //1、建一个Socket
        DatagramSocket datagramSocket = new DatagramSocket(8080);//8080端口号在AB此次传送中没起作用,但是这个端口号意味着,别的计算机可以通过这个端口号给A传送信息
        //2、建一个包
        String msg ="UDP传输!";
        int port=9090;
        InetAddress localhost = InetAddress.getByName("localhost");
        DatagramPacket datagramPacket = new DatagramPacket(msg.getBytes(),0,msg.getBytes().length,localhost,port);
        //3、发送包
        datagramSocket.send(datagramPacket);
        //关闭流
        datagramSocket.close();
    }
}
B端
public class UdpServerDemo01 {
    public static void main(String[] args) throws Exception {
        DatagramSocket datagramSocket = new DatagramSocket(9090);
        //接受数据包
        byte[] buffer = new byte[1024];
        DatagramPacket datagramPacket = new DatagramPacket(buffer, 0, buffer.length);
        datagramSocket.receive(datagramPacket);
        System.out.println(datagramPacket.getAddress());
        System.out.println(new String(datagramPacket.getData(),0, datagramPacket.getLength()));
    }
}
咨询
sender
public class UdpSenderDemo01 {
    public static void main(String[] args) throws  Exception {
        DatagramSocket datagramSocket = new DatagramSocket(6666);
        //循环接收消息,直到接受到88后结束
        while(true){
            //准备接收包裹
            byte[] container = new byte[1024];
            //包
            DatagramPacket datagramPacket = new DatagramPacket(container,0,container.length);
            datagramSocket.receive(datagramPacket);//阻塞式接受包裹
            byte[] data = datagramPacket.getData();
            String receive = new String(data,0,data.length).trim();//trim可以将数据后面连续的空格删除
            System.out.println(receive);
            //接收到“88”  断开链接
            if (receive.equals("88")){
                break;
            }
        }
        datagramSocket.close();
    }
}
receiver
public class UdpReceiverDemo01 {
    public static void main(String[] args) throws Exception {
        DatagramSocket datagramSocket = new DatagramSocket(8888);
        //准备数据:控制台读取
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
        //循环发送消息,直到发送88后结束
        while (true){
            String data = bufferedReader.readLine();
            byte[] datas = data.getBytes();
            //数据包
            DatagramPacket datagramPacket = new DatagramPacket(datas, 0, datas.length, new InetSocketAddress("localhost",6666));
            datagramSocket.send(datagramPacket);
            //断开链接 “88”
            if (data.equals("88")){
                break;
            }
        }
        datagramSocket.close();
        bufferedReader.close();
    }
}
在线咨询:两者都可以是接收方,也可以都是发送方。
多线程的实现
send
public class TalkSend implements Runnable{
    DatagramSocket socket =null;
    BufferedReader bufferedReader =null;
    private int fromport;
    private int toport;
    private String toip;
    public TalkSend(int fromport, int toport, String toip) {
        this.fromport = fromport;
        this.toport = toport;
        this.toip = toip;
        try {
            socket = new DatagramSocket(fromport);
            bufferedReader = new BufferedReader(new InputStreamReader(System.in));
        } catch (SocketException e) {
            e.printStackTrace();
        }
    }
    @Override
    public void run() {
        //循环发送消息,直到发送88后结束
        while (true){
            String data = null;
            try {
                data = bufferedReader.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            byte[] datas = data.getBytes();
            //数据包
            DatagramPacket datagramPacket = new DatagramPacket(datas, 0, datas.length, new InetSocketAddress(this.toip,this.toport));
            try {
                socket.send(datagramPacket);
            } catch (IOException e) {
                e.printStackTrace();
            }
            //断开链接 “88”
            if (data.equals("88")){
                break;
            }
        }
        socket.close();
    }
}
receive
public class TalkReceive implements Runnable{
    DatagramSocket socket =null;
    private int port;
    private String msgfrom;
    public TalkReceive(String msgfrom, int port) {
        this.port = port;
        this.msgfrom = msgfrom;
        try {
            socket=new DatagramSocket(port);
        } catch (SocketException e) {
            e.printStackTrace();
        }
    }
    @Override
    public void run() {
        //循环接收消息,直到接受到88后结束
        while(true){
            //准备接收包裹
            String receive = null;//trim可以将数据后面连续的空格删除
            try {
                byte[] container = new byte[1024];
                //包
                DatagramPacket datagramPacket = new DatagramPacket(container,0,container.length);
                socket.receive(datagramPacket);//阻塞式接受包裹
                byte[] data = datagramPacket.getData();
                receive = new String(data,0,data.length).trim();
                System.out.println(msgfrom+":"+receive);
            } catch (IOException e) {
                e.printStackTrace();
            }
            //接收到“88”  断开链接
            if (receive.equals("88")){
                break;
            }
        }
        socket.close();
    }
}
通信双方
老师
public class TalkStudent {
    public static void main(String[] args) {
        new Thread(new TalkSend(1111,2222,"localhost")).start();
        new Thread(new TalkReceive("老师",3333)).start();
    }
}
学生
public class TalkTeacher {
    public static void main(String[] args) {
        new Thread(new TalkSend(4444,3333,"localhost")).start();
        new Thread(new TalkReceive("学生",2222)).start();
    }
}
1.8、URL
统一资源定位符:定位资源,定位互联网上的某一个资源。
DNS域名解析:将域名转换成IP
如 www.baidu.com   转换成  xxx.xx.xx.xx(IP地址)
URL组成
协议://ip地址://端口/项目名/资源
public class URLDemo01 {
    public static void main(String[] args) throws MalformedURLException {
        URL url = new URL("https://localhost:8080/helloword/index.jsp?username=a&password=123");
        System.out.println(url.getProtocol());//协议  https
        System.out.println(url.getHost());//主机  localhost
        System.out.println(url.getPort());//端口号 8080
        System.out.println(url.getPath());//文件  /helloword/index.jsp
        System.out.println(url.getFile());//全路径 /helloword/index.jsp?username=a&password=123
        System.out.println(url.getQuery());//参数 username=a&password=123
    }
}
下载网络资源
public class URLDown {
    public static void main(String[] args) throws Exception{
        //网易云歌曲
        URL url = new URL("https://m10.music.126.net/20220417220436/90fbe041c8a2df593f43faff5761ee58/yyaac/obj/wonDkMOGw6XDiTHCmMOi/13928008933/2a9d/c491/4dd1/a9e48ef877bab3b3a98ba7824e253c43.m4a");
        //链接这个资源HTTP
        HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
        InputStream inputStream = urlConnection.getInputStream();
//文件输出流
        FileOutputStream fos = new FileOutputStream("11.m4a");
        byte[] buffer = new byte[1024];
        int len;
        while ((len = inputStream.read(buffer))!=-1){
            fos.write(buffer,0,len);
        }
        fos.close();
        inputStream.close();
        urlConnection.disconnect();
    }
}
 
                    
                 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号