Java=网络编程,TCP网络编程

1.网络编程

2.TCP网络编程

一.网络编程

软件架构

C/S架构: 客户端/服务器 比如:QQ,百度网盘,淘宝App
B/S结构: 浏览器/服务器 比如:网页QQ,网页淘宝   

网络通讯协议:网络:互联网。局域网 ---通信:数据传输,-- 协议,规则规范

TCP,IP协议

TCP协议:传输控制协议,

IP协议:因特网协议

3.java中支持的常见协议

TCP协议: 传输控制协议
    特点: 面向有连接(数据传输之前必须先建立连接,底层是通过"三次握手"建立连接)
    优点: 保存数据是完整,安全的 
    缺点: 性能较低    
UDP协议: 用户数据报协议
    特点: 面向无连接(数据传输时不需要关系对方是否存在,甚至不需要关系对象是否开机)
    缺点: 不能保证数据完整和不能保证安全的    
    优点: 性能较高    

4.网络编程的三要素

1.网络通信协议
2.IP地址: 每台连接到互联网的计算机的唯一标识(就类似于人的身份证号,或者电话机的电话号码)  
    组成:由32位二进制组成 0110 0100 0100 0100 0100 0110 0100 0110
        我们通常会搞成10进制:      192.168.120.250    
3.端口号: 一台计算机上不同软件的标识
    端口号一共有0-65535号,其中1024以下的端口被软件厂商占用!!(我们写软件时,用1024以上的)

ip地址分类
IPv4版本:由32位二进制组成,大概42亿种IP,面临枯竭
IPv6版本:由128位二进制组成,大概有可以给地球上每一粒沙子搞一个IP且不重复   

IP地址的相关命令
ipconfig:查看本机IP
ping 对方IP: 测试你和对象网络是否畅通/通畅   

特殊的IP地址
127.0.0.1(localhost): 本机回环地址(相当于Java中this)

InetAddress类

a.InetAddress类代表IP地址类
b.获取本地IP
    InetAddress.getLocalHost();//获取主机(本机)的IP地址对象
c.获取其他机器的IP
    InetAddress.getByName(域名/IP地址);//获取其他机器的IP地址对象
d.成员方法
     String getHostName();获得主机名 
     String getHostAddress();获得IP地址字符串
    
public class InetAddressDemo {
    public static void main(String[] args) throws UnknownHostException {
        //1.获取本机的ip地址对象
        InetAddress local = InetAddress.getLocalHost();
        System.out.println(local);//DESKTOP-7CI8PTA/192.168.1.8
        //2.获取其他机器的IP地址对象
        InetAddress address = InetAddress.getByName("www.baidu.com");
        System.out.println(address);//www.baidu.com/36.102.44.96
        //3.成员方法
        String hostName = address.getHostName();
        String hostAddress = address.getHostAddress();
        System.out.println(hostName);
        System.out.println(hostAddress);
    }
}    

二。TCP通信

TCP通信分为客户端和服务器端

TCP中的两个重要的类

Socket类,代表客户端类 套接字

ServerSocket类,代表服务器端类  服务器端套接字

Socket类构造方法:

public Socket(String ip,int port);//服务器的IP地址,服务器的端口号
此构造非常牛逼!! 会根据传入的参数,自动去连接服务器
    如果连接成功,那么对象正常创建
    如果连接失败,那么直接抛出异常!!

常用方法:‘

public OutputStream getOutputStream();//获取连接通道中输出流
public InputStream getInputStream();//获取连接通道中输入流

public void shutDownOutput();//关闭连接通道中的输出流
public void shutDownInput();//关闭连接通道中的输入流

public void close();//关闭客户端对象

ServerSocket类

构造方法:

public ServerSocket(int port);//指定服务器端使用的端口号

常用成员方法:

public Socket accept();//接收连接到服务器的那个Socket对象,如果暂时没有客户端,该方法会阻塞
public void close(); //关闭服务器端对象

注意: 服务器获取到客户端对象之后,也可以获取连接中两个流,
		但是获取时是输入流还是输出流,相当于服务器而言了

简单的TCP通信实现

客户端给服务器发送信息,服务器不回!
public class SocketDemo {
    public static void main(String[] args) throws IOException {
        //1.创建Socket对象
        Socket socket = new Socket("127.0.0.1",8888);
        System.out.println("连接服务器成功...");
        //2.获取输出流
        OutputStream out = socket.getOutputStream();
        //3.调用输出流的write方法
        out.write("你好我是客户端!".getBytes());
        System.out.println("数据发送成功...");
        //4.释放资源
        out.close();
        socket.close();
        System.out.println("客户端关闭了...");
    }
}

public class ServerSocketDemo {
    public static void main(String[] args) throws IOException {
        //1.创建ServerSocket对象
        ServerSocket server = new ServerSocket(8888);
        System.out.println("服务器启动了...");
        //2.接收连接到的客户端对象
        Socket socket = server.accept(); //阻塞
        System.out.println("有客户端来了...");
        //3.获取输入流
        InputStream in = socket.getInputStream();
        //4.调用输入流的read方法
        byte[] bs = new byte[1024];
        int len = in.read(bs);
        System.out.println("客户端说:"+new String(bs,0,len));
        //5.释放资源
        in.close();
        socket.close();
        server.close();
    }
}

实现简单的TCP通信实现双向

客户端给服务器发信息,服务器接收到之后,给客户端回信息

public class SocketDemo {
    public static void main(String[] args) throws IOException {
        //客户端步骤:
        //1.创建Socket对象
        Socket socket = new Socket("127.0.0.1",9999);
        System.out.println("连接成功...");
        //2.获取输出流
        OutputStream out = socket.getOutputStream();
        //3.调用输出流的write方法
        out.write("你好,我又来了...".getBytes());
        System.out.println("发送成功...");
        //==读取服务器回的信息==
        //4.获取输入流
        InputStream in = socket.getInputStream();
        //5.调用输入流的read方法
        byte[] bs = new byte[1024];
        int len = in.read(bs);
        System.out.println("服务器回复:" + new String(bs, 0, len));
        //================
        //6.释放资源
        in.close();
        out.close();
        socket.close();
        System.out.println("客户端关闭...");
    }
}


public class ServerSocketDemo {
    public static void main(String[] args) throws IOException {
        //服务器的步骤
        //1.创建ServerSocket对象
        ServerSocket server = new ServerSocket(9999);
        System.out.println("服务器启动...");
        //2.接收连接到的客户端对象
        Socket socket = server.accept();//阻塞
        System.out.println("客户端来了...");
        //3.获取输入流
        InputStream in = socket.getInputStream();
        //4.调用输入流的read方法
        byte[] bs = new byte[1024];
        int len = in.read(bs);
        System.out.println("客户端说:" + new String(bs, 0, len));
        //=======回信息========
        //5.获取输出流
        OutputStream out = socket.getOutputStream();

        //6.调用输出流的write方法
        out.write("您的信息我收到了,安息吧!".getBytes());
        System.out.println("成功回复...");
        //====================
        //7.释放资源
        out.close();
        in.close();
        socket.close();
        server.close();
        System.out.println("服务器关闭...");
    }
}

三。综合案例

文件上传:上传图片

//客户端代码实现
public class SocketDemo {
    public static void main(String[] args) throws IOException {
        //文件上传客户端步骤:
        //1.创建Socket
        Socket socket = new Socket("127.0.0.1",9999);
        System.out.println("连接成功...");
        //2.获取输出流
        OutputStream out = socket.getOutputStream();
        //3.创建文件的输入流
        FileInputStream fis = new FileInputStream("555.png");
        //循环:一边读文件,一边发送
        byte[] bs = new byte[1024];
        int len = 0;
        while ((len = fis.read(bs)) != -1) {
            out.write(bs,0,len);
        }
        //添加一句代码,告知服务器文件发送完毕
        socket.shutdownOutput();
        System.out.println("文件上传完毕...");
        //4.获取输入流
        InputStream in = socket.getInputStream();
        //5.读取服务器回复的信息
        len = in.read(bs);
        System.out.println("服务器回复:" + new String(bs, 0, len));
        //6.释放资源
        in.close();
        fis.close();
        out.close();
        socket.close();
        System.out.println("客户端关闭...");
    }
}
//服务器代码实现
public class ServerSocketDemo {
    public static void main(String[] args) throws IOException {
        //文件上传服务器步骤:
        //1.创建ServerSocket
        ServerSocket server = new ServerSocket(9999);
        System.out.println("服务器启动...");
        //2.获取客户端
        Socket socket = server.accept();
        System.out.println("有客户端来了...");
        //3.获取输入流
        InputStream in = socket.getInputStream();
        //4.创建文件的输出流
        FileOutputStream fos = new FileOutputStream(System.currentTimeMillis()+".png");
        //循环:一边读数据,一边写文件
        byte[] bs = new byte[1024];
        int len = 0;
        while ((len = in.read(bs)) != -1) {
            fos.write(bs, 0, len);
        }
        System.out.println("文件保存成功...");
        //5.获取输出流
        OutputStream out = socket.getOutputStream();
        //6.给客户端回信息
        out.write("您的图片我收到了,安息吧~~".getBytes());
        System.out.println("消息回复成功...");
        //7.释放资源
        out.close();
        fos.close();
        in.close();
        socket.close();
        server.close();
        System.out.println("服务器关闭...");
    }
}

扩展:服务器多线程版本

public class ServerSocketMultiDemo {
    public static void main(String[] args) throws IOException {
        //文件上传服务器步骤:
        //1.创建ServerSocket
        ServerSocket server = new ServerSocket(9999);
        System.out.println("服务器启动...");
        //2.获取客户端
        while (true) {
            Socket socket = server.accept();
            System.out.println("有客户端来了...");
            //创建线程
            new Thread(()->{
                try { 
                    //3.获取输入流
                    InputStream in = socket.getInputStream();
                    //4.创建文件的输出流
                    FileOutputStream fos = new FileOutputStream(System.currentTimeMillis() + ".png");
                    //循环:一边读数据,一边写文件
                    byte[] bs = new byte[1024];
                    int len = 0;
                    while ((len = in.read(bs)) != -1) {
                        fos.write(bs, 0, len);
                    }
                    System.out.println("文件保存成功...");
                    //5.获取输出流
                    OutputStream out = socket.getOutputStream();
                    //6.给客户端回信息
                    out.write("您的图片我收到了,安息吧~~".getBytes());
                    System.out.println("消息回复成功...");
                    //7.释放资源
                    out.close();
                    fos.close();
                    in.close();
                    socket.close();
                } catch (IOException ie) {
                    ie.printStackTrace();
                }
            }).start();
        }
        //server.close();
        //System.out.println("服务器关闭...");
    }
}

BS架构模式

扩展,服务器扩展图片显示问题

public class ServerSocketDemo {
    public static void main(String[] args) throws IOException {
        //1.创建服务器
        ServerSocket server = new ServerSocket(12345);
        System.out.println("服务器启动...");
        //2.接收客户端
        while (true) {
            Socket socket = server.accept();
            System.out.println("客户端来了..");
            //3.获取输入流
            InputStream in = socket.getInputStream();
            //4.使用输入流的read方法,把浏览器发送过的数据读取出来
            //我们现在只想读取,客户端要的那个文件
            //a.只读第一行
            BufferedReader br = new BufferedReader(new InputStreamReader(in));
            String line = br.readLine();
            //b.从中获取浏览器想要的那个文件名字
            String[] splits = line.split(" ");
            String fileName = splits[1].substring(1);
            System.out.println("浏览器想要:" + fileName);
            //5.把浏览器想要的文件,读取出来,发送给浏览器
            FileInputStream fis = new FileInputStream(fileName);
            OutputStream out = socket.getOutputStream();
            byte[] bs = new byte[1024];
            int len = 0;
            out.write("HTTP/1.1 200 OK\r\n".getBytes());
            out.write("Content-Type:text/html\r\n".getBytes());
            out.write("\r\n".getBytes());
            while ((len = fis.read(bs)) != -1) {
                out.write(bs, 0, len);
            }
            //5.释放资源
            in.close();
            socket.close();
        }
//        server.close();
//        System.out.println("服务器关闭..");
    }
}

TCP协议下文件上传案例
    什么叫上传: 客户端把其硬盘中文件,通过网络发送到服务器端,并保存到服务器的硬盘中
    上传过程:  a.客户端读取本地文件 b.通过输出流发送给服务器
              c.服务器读取输入流数据 d.保存到服务器的本地
TCP协议下BS案例
    我们不需要自己编写客户端,使用浏览器当过客户端,去访问服务器
        访问时: 127.0.0.1:8888

other=================================



import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

/*
    需求:使用TCP协议实现客户端和服务端互相发送消息。
    客户端发送一条消息,服务器读取之后,返回一条消息给客户端,客户端读取服务器返回的消息之后,又发送一条消息…循环执行,直到输入exit。

    要求:
        1. 消息内容通过键盘输入
        2. 要求服务器端和客户端都使用字符流的方式发送和接收数据。
            使用BufffferedReader方法readLine()读取一行数据。
            使用BufffferedWriter方法write("字符串的数据")发送数据。
 */
public class Server {
    public static void main(String[] args) throws IOException {

        // 创建服务器端对象
        ServerSocket serverSocket = new ServerSocket(7777);

        // 获得socket对象
        Socket socket = serverSocket.accept();

        // 字符输入流
        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));

        // 键盘录入
        Scanner scanner = new Scanner(System.in);

        // 字符输出流
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));

        // 循环
        while(true){
            // 接收客户端的数据
            System.out.println("客户端说:" + br.readLine());

            // 提示:
            System.out.println("服务器说:");
            String line = scanner.nextLine();

            // 判断
            if("exit".equals(line)){
                break;
            }

            // 写出数据(服务器给客户端的相应数据!)
            bw.write(line);
            bw.newLine();
            bw.flush();
        }

        socket.close();
        serverSocket.close();
    }
}



、、---

import java.io.*;
import java.net.Socket;
import java.util.Scanner;

/*
    需求:使用TCP协议实现客户端和服务端互相发送消息。
    客户端发送一条消息,服务器读取之后,返回一条消息给客户端,客户端读取服务器返回的消息之后,又发送一条消息…循环执行,直到输入exit。

    要求:
        1. 消息内容通过键盘输入
        2. 要求服务器端和客户端都使用字符流的方式发送和接收数据。
            使用BufffferedReader方法readLine()读取一行数据。
            使用BufffferedWriter方法write("字符串的数据")发送数据。

 */
public class Client {
    public static void main(String[] args) throws IOException {

        // 创建Scoket对象
        Socket socket = new Socket("127.0.0.1",7777);

        // 字符输出流
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));

        // 键盘录入
        Scanner scanner = new Scanner(System.in);

        // 字符输入流
        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));

        // 无限循环
        while(true){
            System.out.println("客户端说:");
            // 数据来自键盘录入
            String line = scanner.nextLine();

            // 判断
            if("exit".equals(line)){
                // 结束循环
                break;
            }

            // 发送数据(写出数据,客户端向服务器端发送请求的数据!)
            bw.write(line);

            // 换行
            bw.newLine();

            // 一定要flush
            bw.flush();

            // 读取来自服务器端响应的结果数据
            System.out.println("服务器端说:" + br.readLine());

        }

        br.close();
        bw.close();

        socket.close();
    }
}
发布了117 篇原创文章 · 获赞 20 · 访问量 27万+

猜你喜欢

转载自blog.csdn.net/u010581811/article/details/105079687