socket实现网络通信

本文介绍了使用Java的Socket实现网络通信,涵盖了网络通信的要素,包括IP、端口和通信协议。详细讲解了TCP和UDP的区别,以及TCP中的消息传输和文件传输过程。此外,还简单提到了UDP的通信方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

socket实现网络通信

1.1、网络通信的要素

通信双方的地址:

  • IP

  • 端口号

  • 例如:127.0.0.1:8080

网络通信的协议:

TCP/IP参考模型

总结:

  1. 网络编程中有两个问题

    • 如何准确的定位到网络上的一台主机

    • 找到主机之后如何进行通信

  2. 网络编程中的要素

    • IP和端口号(Port)

    • 网络通信协议 UDP、TCP

1.2、IP

IP地址:InetAdress类

  • 唯一定位一台网络上的计算机

  • 127.0.0.1:本机IP(lochost)

  • IP地址分类

    • iPv4/ipv6

    • 公网(互联网)-私网(局域网)

      • ADCD类地址

      • 192.168.xxx.xxx组织内部专用

测试ip

import java.net.InetAddress;
import java.net.UnknownHostException;
//测试Ip
public class TextInetAdress {
    public static void main(String[] args) {
        try {
            //通过名字返回本机IP
            InetAddress inetAdress1 = InetAddress.getByName("127.0.0.1"); 
            System.out.println(inetAdress1);
            //通过名字查询百度网IP地址
            InetAddress inetAdress2 = InetAddress.getByName("www.baidu.com");
            System.out.println(inetAdress2);
            //通过名字返回本机IP
            InetAddress inetAdress3 = InetAddress.getByName("localhost"); 
            System.out.println(inetAdress3);
            //通过名字返回本机IP
            InetAddress inetAdress4 = InetAddress.getLocalHost();  
            System.out.println(inetAdress4);
            //常用方法
            System.out.println(inetAdress2.getHostAddress());//规范的
            System.out.println(inetAdress2.getCanonicalHostName());
            System.out.println(inetAdress2.getHostName());
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
    }
}

1.3、端口

端口表示计算机上的一个进程:

  • 不同的进程有不同的端口号

  • TCP/UDP端口

  • 单个协议下端口号不能冲突

  • 端口分类:

    • 共有端口 0-1023

      • HTTP : 80

      • HTTPS : 443

      • FTP : 21

      • Telent : 23

    • 程序注册端口:2014-49151,分配给用户或者程序

      • Tomcat : 8080

      • MySQL : 3306

      • Oracle : 1521

import java.net.InetSocketAddress;
public class TextInetSocketAddress {
    public static void main(String[] args) {
        InetSocketAddress socketAddress1 = new InetSocketAddress("127.0.0.1", 8080);
        System.out.println(socketAddress1);
        InetSocketAddress socketAddress2 = new InetSocketAddress("localhost", 8080);
        System.out.println(socketAddress2);
    }
}

1.4、通信协议

TCP/IP协议簇

  • TCP:用户传输协议

  • UDP:用户数据报协议

TCP/UDP对比:

TCP

  • 连接服务器

  • 稳定

  • 三次握手,四次挥手

  • 客户端-服务器

  • 传输完成,释放连接,效率低

UDP

  • 不连接服务器

  • 不稳定

  • 无论另一端有无准备,都能发送

1.5、TCP

1.5.1、消息传输

客户端

  1. 连接服务器Socket

  2. 发送消息

import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
//客户端
public class TcpClientDemo1 {
    public static void main(String[] args) {
        Socket socket=null;
        OutputStream os=null;
        try {
            //要知道服务器的地址,端口号
            InetAddress serverIp = InetAddress.getByName("127.0.0.1");
            int port=9999;
            //创建一个socket链接
            socket = new Socket(serverIp,port);
            //发送消息I/O流
            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. 接受用户的消息

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
//服务器端
public class TcpSeverDemo2 {
    public static void main(String[] args) {
        ServerSocket serverSocket=null;
        Socket accept=null;
        InputStream is=null;
        ByteArrayOutputStream baos=null;
        try {
             //我得有一个地址
             serverSocket = new ServerSocket(9999);
            //等待客户端连接过来
             while (true) {
                 accept = serverSocket.accept();
                 //读取客户端的内容
                 is = accept.getInputStream();
                 //管道流
                 baos = new ByteArrayOutputStream();
                 byte[] buffer = new byte[1024]; //创建一个缓冲区
                 int len;  //用来判断是否将缓冲区的字节读完,读完则值为-1
                 while ((len = is.read(buffer)) != -1) {
                 baos.write(buffer, 0, len);//从buffer中写出数据到baos写出长度0-len
                 }
                 System.out.println(baos.toString());
             }
        } catch (Exception 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 (accept!=null)
            try {
                accept.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (serverSocket!=null)
            try {
                serverSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

1.5.2、文件传输

客户端

  1. 读取文件

  2. 创建连接

  3. 发送文件

import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
//读文件发送
public class TcpFileDemo01 {
    public static void main(String[] args) throws Exception {
        //1创建一个socket连接获取端口和地址
        Socket socket=new Socket(InetAddress.getByName("127.0.0.1"),9000);
        //2获取一个输出流
        OutputStream os = socket.getOutputStream();
        //3读文件流
        FileInputStream fis = new FileInputStream(new File("zhushunsheng.jpg"));
        byte[] buffered=new byte[1024];  //自定义一个缓冲区
        int len;                        //用来判断是否将缓冲区的字节读完
        while ((len=fis.read(buffered))!=-1){
            os.write(buffered,0,len);  //从buffer中写出数据到baos写出长度0-len
        }
        //通知服务器我已经结束了
        socket.shutdownOutput();
        //确认服务器接收完毕才能断开连接
        InputStream inputStream = socket.getInputStream();
        //String byte[]
        ByteArrayOutputStream baos=new ByteArrayOutputStream();
        byte[] buffer2=new byte[2014];
        int len2;
        while ((len2=inputStream.read(buffer2))!=-1){
            baos.write(buffer2,0,len2);
        }
        System.out.println(baos.toString());
        //4关闭资源
        baos.close();
        inputStream.close();
        fis.close();
        os.close();
        socket.close();
​
    }
}

服务器

  1. 创建连接

  2. 监听连接

  3. 接收文件

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
//接收文件
public class TcpFileDemo02 {
    public static void main(String[] args) throws Exception {
        //1创建服务
        ServerSocket serverSocket = new ServerSocket(9000);
        //监听客户端的连接
        Socket accept = serverSocket.accept();
        //2获取输入流
        InputStream is = accept.getInputStream();
        //3输出文件
        FileOutputStream fos = new FileOutputStream(new File("receive.jpg"));
        byte[] buffer=new byte[1024];
        int len;
        while ((len=is.read(buffer))!=-1){
            fos.write(buffer,0,len);
        }
        //通知客户端我接收完毕了
        OutputStream os=accept.getOutputStream();
        os.write("我接收完毕了,你可以断开了".getBytes());
        //4关闭资源
        fos.close();
        is.close();
        accept.close();
        serverSocket.close();
    }
}

注意事项:

如果文件在源文件目录下可以采用相对路径找到文件(这里采用此方式),如果文件不在源目录下则应采用绝对路径传输

1.6、UDP

模拟客户端1给客户端2发送消息

客户端1

  1. 创建连接

  2. 创建一个包

  3. 确认发送对象

  4. 发送包

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
//UDP不需要连接服务器
public class UdpClientDemo1 {
    public static void main(String[] args) throws Exception {
        //建立一个socket
        DatagramSocket socket=new DatagramSocket(9999);//DatagramSocket数据报套接字
        //建立一个包
        String msg="你好";
        //发送给谁
        InetAddress lochost=InetAddress.getByName("127.0.0.1");
        int port=9090;
        //参数分别为数据,数据的长度,发送的地址,端口号
        DatagramPacket packet = new DatagramPacket(msg.getBytes(), 0, msg.getBytes().length, lochost, port);
        //发送包
        socket.send(packet);
        //关闭流
        socket.close();
    }
}

客户端2

  1. 开放端口

  2. 接受数据

  3. 关闭连接

import java.net.DatagramPacket;
import java.net.DatagramSocket;
//还是要等待客户端的连接
public class UdpSeverDemo2 {
    public static void main(String[] args) throws Exception {
        //开放端口
        DatagramSocket socket=new DatagramSocket(9090);
        //接收数据
        byte[] buffer= new byte[1024];
        DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length);//接收
        socket.receive(packet);
        //关闭连接
        socket.close();
        System.out.println(packet.getAddress().getHostAddress());
        System.out.println(new String(packet.getData(),0,packet.getLength()));
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不要再卷了Y

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值