JavaSE——day20网络编程

UDP编程

    UDP是无连接的网络,不需要确定接收方是否收到。

不需要建立连接通道的
数据大小有限制
不可靠连接
执行效率高

发送方代码:

package day20T.UDP;

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

public class Send {

	public static void main(String[] args) throws IOException {
		
		//创捷套接字对象
		DatagramSocket ds = new DatagramSocket() ;
		
		//创建发送的包
		byte[] bys = "Hello UDP".getBytes() ;
		int length = bys.length ;
		InetAddress address = InetAddress.getByName("192.168.43.194") ;//这个地址是接收方的地址,根据实际情况设定
		int port = 10088 ;    //完成UDP数据收发需要的条件:①发送方知道接收方的IP地址  ②发送方与接收方具有相同的接口
		
		/**
		 * DatagramPacket(byte[] buf, int length, InetAddress address, int port) 
         * 构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。
		 */
		DatagramPacket dp = new DatagramPacket(bys, length, address, port) ;
		
		ds.send(dp);
		
		ds.close();
	}
}

接收方代码:

package day20T.UDP;

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

public class Receive {

	public static void main(String[] args) throws IOException {

//		InetAddress address = InetAddress.getByName("malaganguo") ;
		//创建套接字对象
		DatagramSocket ds = new DatagramSocket(10088) ;
		
		byte[] bys = new byte[1024] ;
		int length = bys.length;
		
		//创建接收包对象
		DatagramPacket dp = new DatagramPacket(bys, length);
		
		//接受
		ds.receive(dp); 
		
		//获取地址
		InetAddress addr = dp.getAddress() ;
		//将InetAddress转换对象addr转为字符串hostAddr
		String hostAddr = addr.getHostAddress();
		int len2 = hostAddr.length() ;
		
		String data = new String(bys, 0, len2) ; 
		
		System.out.println("当前接受的数据来自" + hostAddr +"是" + data);
	}

}


TCP编程

        TCP协议是面向连接的协议,创建连接时需要进行著名的“3次握手”,断开连接时需要进行著名的“4次挥手”。不过在JAVA中,我们在TCP编程中并不需要手动配置这些东西,java将通信链路的建立和拆除封装成了不同的类,我们面向对象编程中只需要负责调用这些类就就可以了。

    TCP编程的设计思路

          与UDP编程不同,TCP编程是客户机(Client)和服务器(Server)之间的通信,服务器起到转发的功能,负责为客户机提供服务。

           客户端编程:

       ①客户端将自己的文件或者消息发送给服务器之前需要先建立连接。所以需要先创建套接字对象来绑定服务器的IP地址并约定端口号。

                        Socket s = new Socket("这里是地址",这里是端口号(0~65535)) ;//如果是我们自己定义的端口,那么不要用小于1024的!

     ②如果传输的是文件那么需要创建字符缓冲对象来读取文件:    BufferedReader br = new BufferedReader(new FileReader("文件的路径名称")) ;

              如果传输的是我们键盘录入的信息的话,需要创建缓冲区的键盘录入:      BufferedReader br = new BufferedReader(new InputStreamReader(System.in)) ;

       ③创建通道的对象:          BufferedWriter br = new BufferedWriter(new OutputStreamWriter(s.getOutputStream())) ;

       ④一边从br中读取字符流,一边往通道中写入:

                String line = null ;

                while((line=br.readLine()) != null){

                        bw.write(line) ;

                        bw.newLine() ;

                        bw.flush()  ;

                }

       ⑤发送完毕后关闭输出的套接字对象停止发送: s.shutdownOutput() ;

       ⑥如果服务器对客户机发送的数据收到后对客户机有反馈的话,接受这个反馈。创建字符读缓冲区接受来自信道的数据:

            BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream())) ;

            假设只有一行数据,接受: String Client = br.readLine() ;

            在控制台上打印出来:System.out.println(Client) ;


            关闭资源:通道是没有关闭的bw

                             br.close() ;

                             s.close();

一个客户端的Demo:

package day21.TCPupload;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;

public class UploadClient {

	public static void main(String[] args) throws IOException {
		
		//创建套接字对象
		Socket s = new Socket("127.0.0.1" ,12345) ;
		
		//创建字符缓冲区读取文件
		BufferedReader br = new BufferedReader(new FileReader("UserDao.java")) ;
		//创建通道
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream())) ;
		//将读取到的内容写入通道中
		String line = null ;
		while((line=br.readLine()) != null) {
			bw.write(line);
			bw.newLine();
			bw.flush();
		}
		//对于 TCP 套接字,任何以前写入的数据都将被发送,并且后跟 TCP 的正常连接终止序列。如果在shutdown后还有发送数据,那么抛出 IOException
		s.shutdownOutput();
		//接收来自服务器的反馈
		BufferedReader brClient = new BufferedReader(new InputStreamReader(s.getInputStream())) ;
		String client = brClient.readLine() ;
		System.out.println(client);
		//关闭资源
		br.close();
		s.close();
		
	}
}

服务器端编程:

        在TCP创建连接发送数据中,服务器端需要创建的套接字为服务器套接字(不同于UDP,因为是面向连接)。

        ①创建服务器端套接字:    ServerSocket ss = new ServerSocket("这里的端口号需要与客户端约定一致") ;

        ②调用ServerSocket对象的accept()方法,这个方法为对信道的监听器,监听信道中是否有信息,如果有信息,以Socket的类型捕获这个信息到对象中:  Socket accept = ss.accpet() ;

        ③创建读缓冲区的对象,这个缓冲区中用来读取来自监听器得到的输入流,得到监听器中的输入流可以使用监听器对象调用getInputStream()方法: BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream())) ;

        ④创建缓冲区字符输出流对象,用来接受监听器从信道中获取的数据:BufferedWriter bw = new BufferedWriter(new FileReader("这里是一个存储的文件")) ;

        ⑤ 从监听器中一边读出,一边写入服务器端文件中: 

             String line  = null ;

             while((line=br.readLine()) != null){

                    bw.write(line) ;

                    bw.newLine() ;

                    bw.flush() ;

             }

         ⑥ 反馈,告诉客户机这里已经成功接收到了数据:    

                   1)创建缓冲区字符输出流,这个流向监听器中写入数据,用来发送给客户端: BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(accept.getOutputStream())) ;

                       2)向流中写入数据: 

                             bw.write("这里写想要反馈的东西") ;

                             bw.newLine() ;

                             bw.flush() ;

         ⑦关闭资源:accept.close() ;

                              bw.close() ;

总结

    TCP/UDP两个协议在JAVA中编程不仅可以传输手动输入的数据,还可以传输文本文件,图片,音乐等等等等。但是要注意:不仅仅是字符流,在使用字节流缓冲传送图片等资源的时候,也需要调用flush()这个方法,否则可能会出现最后一个缓冲区中的数据接收不到,造成图片等的部分却失。


    TCP/UDP在上面的两个例子中都是在各自的main线程中执行定义的,所以只能是单工的,我们可以创建两条线程,分别实现发送和接受的功能,那么就可以实现双工,接近于聊天室。

    

猜你喜欢

转载自blog.csdn.net/weixin_38930706/article/details/80511355