Java网络编程总结

本文详细介绍Java网络编程的基础概念和技术要点,包括InetAddress、InetSocketAddress、Socket及UDP编程等内容,涵盖客户端和服务端编程流程,帮助读者深入理解并掌握网络编程。

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

1.InetAddress

通过String获取InetAddress
netAddress.getByName(“127.0.0.1”);
InetAddress.getByName(“localhost”);
InetAddress.getLocalHost();

通过InetAddress获取相关信息
InetAddress byName ;
System.out.println(byName);//获取域名+ip地址
System.out.println(byName.getAddress());//获取二进制的ip地址
System.out.println(byName.getCanonicalHostName());//获取String类型的ip地址
System.out.println(byName.getHostAddress());//获取主机ip地址
System.out.println(byName.getHostName());//获取主机域名

2.InetSocketAddress

InetSocketAddress中有private访问权限的hostname,addr(InetAddress类型的变量)和port 三个元素,也就是它和我们之前讲过的InetAddress是组合关系。

绑定套接字地址
InetSocketAddress inetSocketAddress = new InetSocketAddress(“127.0.0.1”, 8080);
输出套接字地址信息
System.out.println(inetSocketAddress.getAddress());
System.out.println(inetSocketAddress.getHostName());
System.out.println(inetSocketAddress.getPort());

3.Socket
3.1、Socket介绍

1、利用套接字(Socket)开发网络应用程序早已被广泛的采用,以至于成为事实 上的标准。
2、网络上具有唯一标识的IP地址和端口号组合在一起才能构成唯一能识别的标识符套接字。即socket = new Socket(serverIp, port);
3、通信的两端都要有Socket,是两台机器间通信的端点。
4、网络通信其实就是Socket间的通信。
5、Socket允许程序把网络连接当成一个流,数据在两个Socket间通过IO传输。
6、一般主动发起通信的应用程序属客户端,等待通信请求的为服务端。
7、Socket分类:
1). 流套接字(stream socket):使用TCP提供可依赖的字节流服务
2). 数据报套接字(datagram socket):使用UDP提供“尽力而为”的数据报服务
在这里插入图片描述

3.2 流套接字

服务端:
1.调用 ServerSocket(int port) :创建一个服务器端套接字,并绑定到指定端口 上。用于监听客户端的请求。
2.调用 accept():监听连接请求,如果客户端请求连接,则接受连接,返回通信 套接字对象。
3.调用 该Socket类对象的 getOutputStream() 和 getInputStream ():获取输出 流和输入流,开始网络数据的发送和接收。
4.关闭ServerSocket和Socket对象:客户端访问结束,关闭通信套接字。

package lesson02;

import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;

//客户端
public class TcpClientDemo01 {
    public static void main(String[] args) {
        Socket socket = null;
        OutputStream outputStream = null;
        try {
            //要知道服务端的地址
            InetAddress serverIp = InetAddress.getByName("127.0.0.1");
            //端口号
            int port = 9998;
            //创建一个socket连接
            socket = new Socket(serverIp, port);
            //发送IO流
            outputStream = socket.getOutputStream();
            outputStream.write("19195216 HongZhiHao".getBytes());
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                if (outputStream != null) {
                    outputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (socket != null) {
                    socket.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}

客户端:
1.创建 Socket:根据指定服务端的 IP 地址或端口号构造 Socket 类对象。若服务器端响应,则建立客户端到服务端的通信路线。若连接失败,则会出现异常。
2.打开连接到 Socket 的输入/出流: 使用 getInputStream()方法获得输入流,使用 getOutputStream()方法获得输出流,进行数据传输
3.按照一定的协议对 Socket 进行读/写操作:通过输入流读取服务器放入线路的信息(但不能读取自己放入路线的信息),通过输出流将信息写入线程
4.关闭 Socket:断开客户端到服务器的连接,释放线路

package lesson02;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

//服务端
public class TcpServerDemo01 {
    public static void main(String[] args) {

        ServerSocket serverSocket = null;
        Socket socket = null;
        InputStream inputStream = null;
        ByteArrayOutputStream byteArrayOutputStream = null;
        try {
            //要有一个地址
            serverSocket = new ServerSocket(9998);
            //while (true) {
                //等待客户端连接过来
                socket = serverSocket.accept();
                //读取客户端的消息
                inputStream = socket.getInputStream();
                //管道流
                byteArrayOutputStream = new ByteArrayOutputStream();
                byte[] buffer = new byte[1024];
                //这边也可以构建一个大小为socket.available的byte数组,socket.available是待接收的byte长度,后面就不需要再while循环了,但是空间消耗会比较大
                int len;
                while ((len = inputStream.read(buffer)) != -1) {
                    byteArrayOutputStream.write(buffer, 0, len);
                }
                //这个地方要注意最后一次写入时,byte数组不一定会被占满,所以会写入很多无意义的空格,读取的时候要考虑使用trim()来消除无用的空格
                System.out.println(byteArrayOutputStream.toString());
            //}

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (byteArrayOutputStream != null) {
                    byteArrayOutputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (socket != null) {
                    socket.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (serverSocket != null) {
                    serverSocket.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

补充1:文件传输

传输文件的话,在客户端内,要文件用流的方式输入到输出流里,再让输出流输出到服务端内。这里用到了一个流过滤器的组合使用,因为文件只能通过文件过滤器来进行传输,但单纯的流的传输用buffer缓冲会快很多,所以将它们组合起来。

bis = new BufferedInputStream(new FileInputStream(new File("me.jpg")));
byte[] buffer = new byte[1024];
int len;
while((len = bis.read(buffer)) != -1){
	writer.write(buffer,0,len);
}

然后在客户端,需要将得到的输入流,再通过流的方式解析成文件。这里也用到了一个流过滤器的组合使用。

BufferedOutputStream reader = new BufferedOutputStream(new FileOutputStream(new File("new_me.jpg")));
byte[] buffer = new byte[1024];
int len;
while((len = is.read(buffer)) != -1){
	reader.write(buffer,0,len);
}

补充2:优雅的半关闭

socket.shutdownOutput();
socket.shutdownInput();

就是当某个端既需要输入流也需要输出流的时候,
为了避免输出流输入到自己的输入流里,可以在输入流结束后,关闭输入流,输出流结束后再关闭输出流,不然的话,程序可能会一直停住(因为另一端可能有accept()这种阻断接受)

3.3 数据报套接字

udp特性:
1.将数据、源、目的封装成数据包,不需要建立连接
2.每个数据报的大小限制在64K内
3.发送不管对方是否准备好,接收方收到也不确认,故是不可靠的
5.可以广播发送
6.发送数据结束时无需释放资源,开销小,速度快

Java udp:
1、类 DatagramSocket 和 DatagramPacket 实现了基于 UDP 协议网络程序。
2、UDP数据报通过数据报套接字 DatagramSocket 发送和接收,系统不保证 UDP数据报一定能够安全送到目的地,也不能确定什么时候可以抵达。
3、DatagramPacket 对象封装了UDP数据报,在数据报中包含了发送端的IP地址和端口号以及接收端的IP地址和端口号。
4、UDP协议中每个数据报都给出了完整的地址信息,因此无须建立发送方和接收方的连接。如同发快递包裹一样。

接收端

package lesson03;

import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class UdpServerDemo01 {
    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);
        System.out.println(new String(packet.getData()));
        //关闭连接
        socket.close();
    }
}

发送端

package lesson03;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class UdpClientDemo01 {
    public static void main(String[] args) throws Exception {
        //1.建立一个socket
        DatagramSocket socket = new DatagramSocket();
        //2.建个包
        String msg = "helloWorld";
        InetAddress localhost = InetAddress.getByName("localhost");
        int port = 9090;
        //数据,发给谁,发什么
        DatagramPacket packet = new DatagramPacket(msg.getBytes(), 0, msg.getBytes().length,localhost,port);
        //3.发送包
        socket.send(packet);
        //4.关闭流
        socket.close();
    }
}

4.总结与补充

学好java网络编程,首先得了解套接字和tcp、udp等计算机网络的概念,并且对io流要足够的熟悉,因为网络编程的本质就是流的传输。网络编程方面可以考虑使用Java7引进的try-with-resources的语法糖,来避免写大量的关闭流代码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值