Java Day17:网络编程

1. 网络相关概念

  • 网络通信
    1.概念:两台设备之间通过网络实现数据传输
    2.网络通信;将数据通过网络从一台设备传输到另一台设备
    3.java.net包下提供了一系列的类或借口哦,供程序员使用,完成网络通信

  • 网络
    1.概念:两台或多台设备通过一定物理设备连接起来构成了网络
    2.根据网络的覆盖范围不同,对网络进行分类:
    局域网:覆盖范围最小,仅仅覆盖一个教室或一个机房
    城域网:覆盖范围较大,可以覆盖一个城市
    广域网:覆盖范围最大,可以覆盖全国,甚至全球,万维网是广域网的代表

  • ip地址
    1.概念:网络中每台计算机/主机的唯一标识
    2.查看ip地址:ipconfig
    3.ip地址的表示形式:ipv4 32位十进制 00.00.00.00
    ipv6 128位十六进制 xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx
    4.每一个十进制数的范围:0~255
    5.ip地址的组成:网络地址+主机地址=163.196.10.1 (163.196.10就是网络地址 1是主机地址)
    6.IPv6是Ipv4的升级,尚在推广普及中,现在用的最多的还是IPv4

  • ip地址的分类
    1.按IP地址分类
    IPv4分为A类、B类、C类、D类、E类
    本机:127.0.0.1
    2.公网(互联网) - 私网(局域网)

  • 域名
    1.www.baidu.com
    2.方便记忆
    3.概念:将ip地址映射成域名

  • 端口号
    1.概念:用于标识计算机上某个特定的网络程序
    2.表示形式:以整数形式,范围0~65535
    3.0~1024已经被占用
    4.常见的网络程序端口号:
    tomcat:8080
    mysql:3306
    oracle:1521
    sqlserver:1433

  • 网络通信协议
    http、ftp、smtp、TCP
    OSI七层网络模型:应用层、表示层、会话层、传输层、网络层、数据链路层、物理层
    TCP/IP四层概念模型:应用层、传输层、网络层、数据链表层
    TCP/UTP是属于传输层的协议
    1.网络编程有两个主要的问题:如何定位网络上的一台、多台主机?找到主机之后如何进行通信?
    2.网络编程中的要素:IP和端口号、网络通信协议

  • Java中IP对应的类
    InetAddress

2.TCP

2.1.客服端

  • 主要任务
    1.通过Socket连接服务器
    2.发送数据
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;

public class C {
    public static void main(String[] args) throws IOException {
        String ip = "127.0.0.1";
        InetAddress serverIP = InetAddress.getByName(ip);
        int port = 6080;
        Socket socket = new Socket(serverIP,port);
        OutputStream os = socket.getOutputStream();
        os.write("你好,本地".getBytes());
        os.close();
        socket.close();
    }
}

2.2 服务器

  • 主要任务
    1.建立服务器
    2.等待客户端连接
    3.接收数据
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class S {
    public static void main(String[] args) {
        ServerSocket serverSocket = null;
        Socket socket = null;
        InputStream is = null;
        PrintStream ps = System.out;

        {
            try {
                serverSocket = new ServerSocket(6080);
                socket = serverSocket.accept();
                is = socket.getInputStream();
                int len;
                byte[] bytes = new byte[1024];
                while ((len=is.read(bytes))!=-1){
                    ps.write(bytes,0,len);
                }

            } catch (IOException e) {
                throw new RuntimeException(e);
            }finally {
                ps.close();
                if (is!=null){
                    try {
                        is.close();
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                }
                if (socket!=null){
                    try {
                        socket.close();
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                }

                if (serverSocket!=null){
                    try {
                        serverSocket.close();
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        }
    }
}

服务器启动后,会等待客户端建立连接,以便接收数据,一般一台服务器服务于多个客户端,因此等待连接的命令是循环的。

2.3 TCP传输文件

将图片上传

  • 服务器端
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class S {
    public static void main(String[] args) {
        ServerSocket serverSocket = null;
        Socket socket = null;
        InputStream is = null;
        FileOutputStream fos = null;

        {
            try {
                serverSocket = new ServerSocket(6080);
                socket = serverSocket.accept();
                is = socket.getInputStream();
                fos = new FileOutputStream(new File("ok.jpg"));
                int len;
                byte[] bytes = new byte[1024];
                while ((len=is.read(bytes))!=-1){
                    fos.write(bytes,0,len);
                }

            } catch (IOException e) {
                throw new RuntimeException(e);
            }finally {
                if (fos!=null){
                    try {
                        fos.close();
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                }
                if (fos!=null){
                    try {
                        fos.close();
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                }
                if (is!=null){
                    try {
                        is.close();
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                }
                if (socket!=null){
                    try {
                        socket.close();
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                }

                if (serverSocket!=null){
                    try {
                        serverSocket.close();
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        }
    }
}
  • 客户端
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;

public class C {
    public static void main(String[] args) throws IOException {
        String ip = "127.0.0.1";
        String filePath = "e:/licen.jpg";
        InetAddress serverIP = InetAddress.getByName(ip);
        int port = 6080;
        FileInputStream fis = new FileInputStream(filePath);
        Socket socket = new Socket(serverIP,port);
        OutputStream os = socket.getOutputStream();
        byte[] bytes = new byte[1024];
        int len = 0;
        while ((len=fis.read(bytes))!=-1){
            os.write(bytes,0,len);
        }
        os.close();
        socket.close();
        fis.close();
    }
}

我们在上传文件时,需要再客户端先将内存的文件读取到idea中(输入流),再上传数据到服务器(输出流),同样,服务器先接收数据(输入流),在输出保存数据到内存(输出流)。

3. UDP

不同于TCP,UDP不需要建立连接,就可以对接收端发送数据。

3.1 发送端

public class UdpC {
    public static void main(String[] args) throws Exception {
        //建立Socket
        DatagramSocket socket = new DatagramSocket();
        //建立信息
        String mes = "Hello ah ,brother shu";
        //地址信息
        InetAddress localhost = InetAddress.getLocalHost();
        int port = 6080;
        //创建包,数据,数据的长度,发送地址
        DatagramPacket packet = new DatagramPacket(mes.getBytes(),0,mes.getBytes().length,localhost,port);
        //发送包
        socket.send(packet);
        //关闭流
        socket.close();
    }
}

我们即使没有与接收端建立连接,也可以发送数据,代码也能正常运行。

3.2 接收端

public class UdpS {
    public static void main(String[] args) throws Exception {
        //开放端口
        DatagramSocket socket = new DatagramSocket(6080);
        //接收数据包
        byte[] buffer = new byte[1024];
        DatagramPacket packet = new DatagramPacket(buffer,0,buffer.length);
        //阻塞接收
        socket.receive(packet);
        //输出数据来源,输出数据
        System.out.println(packet.getAddress().getHostAddress());
        System.out.println(new String(packet.getData(),0,packet.getLength()));
        //关闭流
        socket.close();
    }
}

服务器成功接收

在建立服务器后,可以接收到数据。

3.3 聊天建立

  • 发送
public class UdpSender {
    public static void main(String[] args) throws Exception {
        //端口
        DatagramSocket socket = new DatagramSocket(6688);
        //接收输入
        BufferedReader bufR = new BufferedReader(new InputStreamReader(System.in));
        //建立包
        while (true){
            String sdata = bufR.readLine();
            byte[] data = sdata.getBytes();
            DatagramPacket packet = new DatagramPacket(data,0,data.length,new InetSocketAddress("localhost",6655));
            //发送包
            socket.send(packet);
            //关闭流
            if (sdata.equals("close"))
            break;
        }
        bufR.close();
        socket.close();
    }
}

  • 接收
public class UdpReceive {
    public static void main(String[] args) throws Exception {
        //端口
        DatagramSocket socket = new DatagramSocket(6655);
        //接收包
        byte[] container = new byte[1024];
        DatagramPacket packet = new DatagramPacket(container,0,container.length);
        while (true){
            //接收数据
            socket.receive(packet);
            byte[] data = packet.getData();
            int len = data.length;
            String rdata = new String(data,0,len);
            System.out.println(rdata.trim());
            //停止聊天
            if (rdata.trim().equals("close")){
                break;
            }
        }
        socket.close();
    }
}

注意
因为没有建立连接,并且刚刚开始运行时,没有接收到包输入,这里container数组的长度是1024,除了有效的输入,其他位置会默认为0,导致我们的包的数据长度也是1024,包括下面拿出包里的数据,转换成字符串时,字符串会在有效的数据后加上空,输出时我们要输出String.trim(),保证只输出有效字符,我在寻找更有效的解决办法,能解决一开始的字节数组会自动填充0的问题。

3.4 多线程实现互相聊天

  • 接收工具类
public class Recive extends Thread{

    DatagramSocket socket = null;    //端口

    int port;
    public Recive(int port) throws SocketException {
        this.port = port;
        socket = new DatagramSocket(port);
    }
    @Override
    public void run() {
        while (true){
            //接收包
            byte[] container = new byte[1024];
            DatagramPacket packet = new DatagramPacket(container,0,container.length);
            //接收数据
            try {
                socket.receive(packet);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            byte[] data = packet.getData();
            int len = data.length;
            String rdata = new String(data,0,len);
            System.out.println(rdata.trim());
            //停止聊天
            if (rdata.trim().equals("close")){
                break;
            }
        }
        socket.close();
    }
}
  • 发送工具类
public class Send extends Thread{

    DatagramSocket socket;  //端口
    //接收输入
    BufferedReader bufR ;
    String ip;
    int port;
    int toport;
    public Send(String ip,int port,int toport) throws SocketException {
        this.ip = ip;
        this.port=port;
        this.toport = toport;
        socket = new DatagramSocket(port);
        bufR = new BufferedReader(new InputStreamReader(System.in));
    }
    @Override
    public void run() {
        //建立包
        while (true){
            String sdata ;
            try {
                sdata = bufR.readLine();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            byte[] data = sdata.getBytes();
            DatagramPacket packet = new DatagramPacket(data,0,data.length,new InetSocketAddress(ip,toport));
            //发送包
            try {
                socket.send(packet);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            //关闭流
            if (sdata.equals("close"))
                break;
        }
        try {
            bufR.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        socket.close();
    }
}
  • 用户
public class chatUser {
    public static void main(String[] args) throws Exception {
        Send send = new Send("localhost",6685,6688);
        Recive recive = new Recive(6655);
        send.start();
        recive.start();
    }
}

public class chatUser2 {
    public static void main(String[] args) throws Exception {
        Send send = new Send("localhost",6658,6655);
        Recive recive = new Recive(6688);
        send.start();
        recive.start();
    }
}

  • 对话效果

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值