Java基础--网络编程(TCP、UDP)

mac2026-01-15  2

网络编程

文件的上传下载实际就是读入写出的过程如果是文本文件建议用字符流,如果是图片或者其他的文件,建议用字节流+处理流

IP、端口号和Socket

目的:直接或间接的通过网络协议与其他计算机实现数据交换,通讯

两个问题:

如何准确的定位到网络上的一台或多台主机,或者定位到主机上特定的应用 IP端口号 找到主机后如何可靠高效的进行数据传输 OSI参考模型:通讯协议

网络通信协议

OSI参考模型: 应用层:直接面向用户的一层,用户的通信内容要由应用进程解决表示层:应用过程之间传送的信息提供表示方法的服务。会话层:负责维护两个节点之间的传输联接,确保点到点传输不中断,以及管理数据交换等功能传输层:数据传输网络层:数据在节点之间传输创建逻辑链路,通过路由选择算法为分组选择最佳路径,从而实现拥塞控制、网络互联等功能数据链路层:通信实体问建立数据链路联接,传输的基本单位为“帧”物理层:最底层,物理层传输的基本单位是比特流 实际上的TCP/IP参考模型 应用层:HTTP、FTP、DNS传输层:TCP、UCP网络层:IP、ICMP、ARP物理+数据链路层:Link

IP地址:InetAddress类

Java中Inetaddress来代表一个类,一个对象就是一个IP

InetAddress常用方法

静态方法: getByName(String str);获取IP对象getLocalhost();获取本地ip 非静态常用方法: getHostName();获取ip对象的域名getHostAddress(); 获取地址 public static void main(String[] args) { try { InetAddress ip = InetAddress.getByName("www.baidu.com"); System.out.println(ip);//www.baidu.com/61.135.169.121 InetAddress ip2 = InetAddress.getByName("192.168.1.1"); System.out.println(ip2);///192.168.1.1 InetAddress ip3 = InetAddress.getLocalHost(); System.out.println(ip3);//LAPTOP-IA3LU4GJ/169.254.193.252 //获取域名 String yuming = ip.getHostName(); System.out.println(yuming);//www.baidu.com //获取ip地址 String ipAddress = ip.getHostAddress(); System.out.println(ipAddress);//61.135.169.125 } catch (Exception e) { e.printStackTrace(); } } 端口号: 标识正在计算机上运行的进程不同的进程有不同的端口号tomcat默认占用8080,HTTP一般占用80,FTP一般是21,mysql3306 端口号和IP共同构成一个网络套接字: Socket

通讯协议,TCP和UDP

TCP:使用TCP协议前,会建立TCP连接,形成传输数据通道 - 传输使用三次握手方式,点对点通信,可靠的 - TCP协议进行通信的两个应用程序:客户端、服务端 - 在连接中可进行大数据量的传输 - 传输完毕,需要释放连接,效率低

UDP:将数据、源、目的封装成数据包,不需要建立连接 - 每个数据包大小在64k内 - 只管发,不管其他的,接收方也不确认,不可靠传输 - 可以广播发送 - 无需释放资源,效率高,速度快

三次握手(TCP建立可靠连接的依据/实现)

第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SENT状态,等待服务器确认;SYN:同步序列编号第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(seq=k),即SYN+ACK包,此时服务器进入SYN_RECV状态第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手

四次挥手(连接终止协议)

TCP客户端发送一个FIN终止报文,用来关闭客户到服务器的数据传送。服务器收到这个FIN终止报文,它发回一个ACK,确认序号为收到的序号加1。和SYN一样,一个FIN将占用一个序号。服务器关闭客户端的连接,发送一个FIN给客户端。客户端发回ACK报文确认,并将确认序号设置为收到序号加1。

实现TCP的网络编程

客户端发送信息给服务器端发送信息,服务器端将数据显示在控制台

服务器端:

创建一个服务器端套接字,用于绑定端口号设置该端口为可接收状态给服务器端的套接字端输入流对象,用于读取数据循环读取数据,通过ByteArrayOutputStream类写入数据,而是写到了该类中关闭资源

客户端:

创建ip地址对象找到ip创建套接字对象,写入ip地址和端口号给套接字一个输出流,用于写出数据写出数据到实体流中关闭资源 public void Server(){ //1. 创建服务器端端口对象 ServerSocket ss = new ServerSocket(8899); //2. 设置该端口为可接收状态 Socket socket = ss.accept(); //3. 获取输入流 ---Returns an input stream for this socket. InputStream is = socket.getInputStream(); //4. 从务器端写出数据, 他没有指定写入到哪,而是写到了该类中的一个数组中 ByteArrayOutputStream bis = new ByteArrayOutputStream(); byte[] bytes = new byte[10]; int len; while((len = is.read(bytes)) != -1){ bis.write(bytes,0,len); } //打印到控制台 System.out.println(bis.toString()); //5. 关闭资源 bis.close(); is.close(); socket.close(); ss.close(); } TCP编程:客户端发送文件给服务器端,服务器端把该文件存入到本地 /** * 服务器端从socket的输出流中,接收数据,读取,然后输出流存储到本地 */ public void Server(){ //1. 创建端口 ServerSocket sso = new ServerSocket(8899); //2. 设置端口为可接收状态 Socket socket = sso.accept(); //3. 创建接收流,用于接收socket信息 InputStream is = socket.getInputStream();//接受流 //4. 创建输出流,用于将读取的文件存入本地 FileOutputStream fos = new FileOutputStream(new File("D:\\IdeaProjects\\JavaDemo\\sou\\图片05.jpg")); //接收流开始读取数据 byte[] bytes = new byte[1024]; int len; while((len = is.read(bytes)) != null){ //输出流,写入文件内容 fos.write(bytes,0,len); } //5. 关闭资源 fos.close(); is.close(); socket.close(); } /** * 客户端从本地读取一个文件,传输到socket中,发送给服务器端 */ @Test public void Client(){ //1. 发送前写清ip地址和端口号 InetAddress ip = InetAddress.getByName("127.0.0.1"); Socket socket = new Socket(ip,8890); //2. 创建输出流,用于输出读取的文件 OutputStream os = socket.getOutputStream();//输出流 //3. 创建输入流,读取本地文件写入到输出流中 FileInputStream fis = new FileInputStream(new File("D:\\IdeaProjects\\JavaDemo\\sou\\图片04.jpg")); //读入 写出 byte[] bytes = new byte[1024]; int len; while((len = fis.read(bytes)) !=null){ //写出文件内容到socket中 os.write(bytes,0,len); } //4. 关闭资源 fis.close(); os.close(); socket.close(); } 在2基础上添加 服务器回复“图片已上传,谢谢”这句话,客户端接收 /** * 服务器端从socket的输出流中,接收数据,读取,然后输出流存储到本地 */ public void Server(){ //1. 创建端口 ServerSocket sso = new ServerSocket(8899); //2. 设置端口为可接收状态 Socket socket = sso.accept(); //3. 创建接收流,用于接收socket信息 InputStream is = socket.getInputStream();//接受流 //4. 创建输出流,用于将读取的文件存入本地 FileOutputStream fos = new FileOutputStream(new File("D:\\IdeaProjects\\JavaDemo\\sou\\图片05.jpg")); //接收流开始读取数据 byte[] bytes = new byte[1024]; int len; while((len = is.read(bytes)) != null){ //输出流,写入文件内容 fos.write(bytes,0,len); } //5.服务器端接收完毕,发送一段话给客户端 OutputStream os = socket.getOutputStream();//写出 os.write("图片已上传,谢谢".getBytes()); //6. 关闭资源 os.close(); fos.close(); is.close(); socket.close(); } /** * 客户端从本地读取一个文件,传输到socket中,发送给服务器端 */ @Test public void Client(){ //1. 发送前写清ip地址和端口号 InetAddress ip = InetAddress.getByName("127.0.0.1"); Socket socket = new Socket(ip,8890); //2. 创建输出流,用于输出读取的文件 OutputStream os = socket.getOutputStream();//输出流 //3. 创建输入流,读取本地文件写入到输出流中 FileInputStream fis = new FileInputStream(new File("D:\\IdeaProjects\\JavaDemo\\sou\\图片04.jpg")); //读入 写出 byte[] bytes = new byte[1024]; int len; while((len = fis.read(bytes)) !=null){ //写出文件内容到socket中 os.write(bytes,0,len); } //4. 客户端接收服务器发送的数据,并读取 InputStream is = socket.getInputStream();//读入 ByteArrayOutputStream baos = new ByteArrayOutputStream();//写出到控制台 byte[] bytes1 = new bytes[1024]; int len1; while((len1 = is.read(bytes1) != -1){ baos.write(bytes1,0,len); } System.out.println(baos.toString()); //5. 关闭资源 baos.close(); is.close(); fis.close(); os.close(); socket.close(); }

UDP编程

/** * UDP网络编程 发送端和接收端 */ @Test public void sender(){ DatagramSocket socket = null; try { //1. 创建一个socket来发送 socket = new DatagramSocket(); //2. 把一些信息打包给DatagramPacket String str = "这是一个UDP数据"; byte[] data = str.getBytes(); InetAddress ip = InetAddress.getByName("127.0.0.1"); // 把一切信息都打包起来发送 DatagramPacket packet = new DatagramPacket(data,0,data.length,ip,8850); //3. 将包由socket发送 socket.send(packet); } catch (IOException e) { e.printStackTrace(); } finally { if(socket != null){ //4. 关闭资源 socket.close(); } } } @Test public void receiver(){ DatagramSocket socket = null; try { //1. 创建socket socket = new DatagramSocket(); //2. 接收包,用数组存储数据 byte[] data = new byte[1024]; DatagramPacket packet = new DatagramPacket(data,0,data.length); //3. 接收包数据,从0到数组长度 socket.receive(packet); } catch (IOException e) { e.printStackTrace(); } finally { if(socket != null){ //4. 关闭资源 socket.close(); } } }

下载案例

URL下载案例,tomcat下webapps中存放静态资源,创建url对象,找到资源路径创建url连接 先打开连接,返回连接对象再通过连接对象进行连接读入(从流中读取文件信息)写出(边读边写到本地硬盘中) 关闭连接 public void downloadTest(){ //1. 指定URL资源 URL url = new URL("http://localhost:8080/example/ju.png"); //2. 返回一个url打开连接对象 HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); //3. 连接 urlConnection.connect(); InputStream is = urlConnection.getInputStream(); FileOutputStream fos = new FileOutputStream("蓝屏01.png"); byte[] bytes = new byte[1024]; int len; while((len = is.read(bytes)) != -1){ fos.write(bytes,0,len); } fos.close(); is.close(); urlConnection.disconnect(); }
最新回复(0)