黑马程序员 网络编程

 ----------android培训java培训、java学习型技术博客、期待与您交流! -----------

1,UDP协议

          UDP俗称用户数据报协议,它的特点是:

 UDP协议是面向非连接的协议,主要应用在数据传输要求通信效率较高的场合,不需要事先进行连接,传输的数据量也比较小,但是可靠性较小。

          UDP中两个重要的类是DatagramSocket,DatagramPacket,它们的特点如下

          1, 构造方法中凡是带有IP和PORT的DatagramPacket的数据报包都是用来发送的数据报包,否则都是用于接收的数据报包。
          2, DatagramSocket仅仅负责数据的发送和接收,而对数据的封装工作全部由DatagramPacket类的构造进行了封装。
               因此DatagramSocket仅仅负责从本机发出数据或者在本机接受数据。
               因此DatagramSocket的构造方法仅仅涉及本机IP和端口号的传参。
               由于Socket本身位于本机的App上面,因此就算不指定本机的IP或者端口,系统也会根据内部的参数自动获取到本机的IP或者App对象的端口号。
               因此,可以有空参数的构造函数
         3,  DatagramPacket如果是在发送端,则要指明发送的目的地址和对应的端口号,如果在接受端,则不需要
              DatagramSocket用于发送和接受数据,不过需要指明源地址和对应的端口
         4,  DatagramSocket主要有两种方法sen和receive,参数是DatagramPacket
示例代码:

发送端:

/*
需求:通过UDP传输方式,将一段文字数据发送出去
思路:
    1.建立UDPSocket服务,即建立端点
    2.提供数据,并将其封装到数据报包中
    3.通过Socket服务的发送功能,将数据报发送出去
    4.关闭资源
*/
class UdpSend{
    public static void main(String[] args) throws Exception{
       //1.创建UDP服务。通过DatagramSocket建立
       DatagramSocket ds =new DatagramSocket();
       //2.确定数据并封装成数据包
       byte[] buf ="UDP is coming...".getBytes();
      DatagramPacket dp =new DatagramPacket(buf, buf.length, InetAddress.getByName("127.0.0.1"), 10000);
       //3.通过Socket服务将已有数据通过send方法发送出去
       ds.send(dp);
       //4.关闭资源
       ds.close();
    }
}

接收端:

/*
 * 	需求:	定义一个App用于接收通过UDP协议传输过来的数据
	思路:	1,UDP接收端的操作流程
			2,建立UDPSocket服务,即建立Socket接收端点。
			3,定义一个数据报包。因为要存储接收到通过UDP传输来的字节数据,并且接收到的数据有很多信息。
			如果自行提取会非常麻烦。因此直接封装成数据报包对象,调用该对象不同的方法从而获取接收到的数据报包中的信息。
			(直接利用DataPacket类的JavaBean的Getter方法获取各种信息)
			4,通过UDP接收端的Socket的receive方法将接收到的数据取出,并存入已定义好的数据报包对象中。
			5.关闭Socket资源。
 * */
class UdpRece{
    public static void main(String[] args) throws Exception{
       //1、创建udp Socket服务,建立端点
       DatagramSocket ds =new DatagramSocket(10000);
       while(true){
           //2、定义数据报包对象,用于接收发送过来的数据
           byte[] buf =new byte[1024];
           DatagramPacket dp =new DatagramPacket(buf, buf.length);
           //3、通过udpSocket服务的receive方法将数据存入定义好的数据报包
           ds.receive(dp);
           //4、通过数据报包的方法来获取不同的方法
           String ip =dp.getAddress().getHostAddress();
           String data =new String(dp.getData(), 0,dp.getLength());
           int port =dp.getPort();
           System.out.println(ip+"::"+ data+ "::"+ port);
       }
      
       //5、关闭资源
       //ds.close();
    }
}

验证结果:(补充先开启接收端,在开发送端)


2,读取键盘录入

         发送端可以发送键盘录入的信息给接收端。

发送端代码:

class udpsend1{
	public static void main(String[] args) throws IOException {
		DatagramSocket ds = new DatagramSocket(10003);
		BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
		String line = null;
		while((line = bufr.readLine())!=null){
			if("886".equals(line)){
				break;
			}
			byte[] buf =line.getBytes();  
			DatagramPacket dp =new DatagramPacket(buf, buf.length, InetAddress.getByName("127.0.0.1"), 10004);  
			System.out.println(InetAddress.getLocalHost().toString());  
			ds.send(dp);  
		}
		ds.close();
	}
}

接收端代码:

class udpreceive1{
	public static void main(String[] args) throws IOException {
		DatagramSocket ds = new DatagramSocket(10004);
		while(true){
			 byte[] buf =new byte[1024];  
			 DatagramPacket dp =new DatagramPacket(buf, buf.length);  
			 ds.receive(dp);  
			 String ip = dp.getAddress().getHostAddress();  
			 String data = new String(dp.getData(),0,dp.getData().length);
			 System.out.println(ip+"::"+ data);  
		}
	}
}

验证结果:



3,简单聊天程序,实现一个窗口显示

发送端代码:

class Send implements Runnable{
    private DatagramSocket ds;
    public Send(DatagramSocket ds){
       this.ds =ds;
    }
 
    public void run(){
       try{
           //键盘录入
           BufferedReader bufr =
              new BufferedReader(new InputStreamReader(System.in));
           String line =null;
 
           while((line =bufr.readLine())!=null){
              if("886".equals(line))
                  break;    
              byte[] buf =line.getBytes();
              DatagramPacket dp =new DatagramPacket(buf, buf.length, InetAddress.getByName("127.0.0.1"), 10002);
              ds.send(dp);
           }
           ds.close();
       }catch(Exception e){
           throw new RuntimeException("Send Failure!");
       }
    }
}

接收端代码:

class Rece implements Runnable{
    private DatagramSocket ds;
    public Rece(DatagramSocket ds){
       this.ds =ds;
    }
 
    public void run(){
           try{
              while(true){
              byte[] buf =new byte[1024];
              DatagramPacket dp =new DatagramPacket(buf, buf.length);
             
              ds.receive(dp);
              String ip = dp.getAddress().getHostAddress();
              String data =new String(dp.getData(), 0,dp.getLength());
 
              System.out.println(ip+"::"+ data);
              }
           }catch(Exception e){
              throw new RuntimeException("Receive Failure!");
           }
    }
}

调用函数:

class ChatDemo
{
    public static void main(String[] main) throws Exception{
       DatagramSocket sendSocket =new DatagramSocket();
       DatagramSocket receSocket =new DatagramSocket(10002);
 
       new Thread(new Send(sendSocket)).start();
       new Thread(new Rece(receSocket)).start();
    }
}

验证结果:


4,TCP协议

          TCP协议是面向连接的协议,主要应用在数据传输要求完整性较高的场合,需要经过三次握手,才能进行通信传输的数据量一般较大,可靠性较高。
a,简单的数据传送

需求:给服务器端发送一个文本数据

class TcpClient{
    public static void main(String[] args) throws Exception{
       //1. 创建客户端Socket服务,指定目的主机和端口
       Socket s =new Socket("127.0.0.1", 10003);
 
       //2.为了发送数据,应该获取Socket中的输出流
       OutputStream out =s.getOutputStream();
       //3.写数据到输出流,并随网络发送到对应主机
       out.write("TCP is coming....".getBytes());
      
       //4.关闭Socket资源对应的流资源不用关闭
       s.close();
    }
}

需求:定义端接收数据,并打印在控制台上

class TcpServer{
    public static void main(String[] args) throws Exception{
       //1.建立服务器端Socket服务,并监听一个端口
       ServerSocket ss =new ServerSocket(10003);
       //2.通过accept方法来获取连接过来的客户端对象  Server端本身没有流
           //必须使用客户端对象的流对象与客户端本身进行通讯
       Socket s =ss.accept();
       InputStream in =s.getInputStream();
       //获取客户端的IP
       String ip = s.getInetAddress().getHostAddress();
       System.out.println(ip+"....connected!");
       byte[] buf =new byte[1024];
       int len =in.read(buf);
       System.out.println(new String(buf, 0, len));
       //客户端一定要关闭客户端的Socket对象
       s.close();
       ss.close();//服务器端对象的关闭操作是可选的
    }
}

验证结果:


b,服务器循环读取客户端的输入信息

客户端:

public static void main(String[] args) throws UnknownHostException, IOException {
		Socket s = new Socket("127.0.0.1",10005);
		BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
		BufferedWriter bufout = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
		String line = null;
		while((line = bufr.readLine())!=null){
			/*
			 * BufferedWriter使用比较麻烦需要写三句话,如果忘记,容许造成双卡现象
			 * 改用PrintWriter
			 * */
			bufout.write(line);
			bufout.newLine();
			bufout.flush();
			if("over".equals(line))
				break;
		}
		BufferedReader bufin = new BufferedReader(new InputStreamReader(s.getInputStream()));
		String str = bufin.readLine();
		System.out.println(str);
		bufr.close();
		s.close();
	}

服务端:

public static void main(String[] args) throws IOException {
		ServerSocket ss = new ServerSocket(10005);
		Socket s = ss.accept();
		BufferedWriter bufout = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
		BufferedReader bufin = new BufferedReader(new InputStreamReader(s.getInputStream()));
		String line = null;
		while((line = bufin.readLine())!=null){
			System.out.println(line);
			if("over".equals(line))
				break;
		}
		bufout.write("输入结束");
		bufout.newLine();
		bufout.flush();
		s.close();
		ss.close();
	}

验证结果:

c,客户端上传文本文件

客户端代码:

public static void main(String[] args) throws UnknownHostException, IOException {
		Socket s = new Socket("127.0.0.1",10006);
		BufferedReader bufr = new BufferedReader(new InputStreamReader(new FileInputStream("ReadIn.java")));
		PrintWriter bufout = new PrintWriter(s.getOutputStream(),true);
		String line = null;
		while((line = bufr.readLine())!=null){
			bufout.println(line);
		}
		s.shutdownOutput();
		BufferedReader bufin = new BufferedReader(new InputStreamReader(s.getInputStream()));
		String str = bufin.readLine();
		System.out.println(str);
		bufr.close();
		s.close();
	}

服务端代码:

public static void main(String[] args) throws IOException {
		ServerSocket ss = new ServerSocket(10006);
		Socket s = ss.accept();
		PrintWriter pw = new PrintWriter(new FileOutputStream("data_serv.txt"),true);
		PrintWriter out = new PrintWriter(s.getOutputStream(),true);
		BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
		String line = null;
		while((line = in.readLine())!=null){
			pw.println(line.toUpperCase());
		}
		out.println("上传成功");
		pw.close();
		s.close();
		ss.close();
	}

验证结果:



d,实现图片的上传

客户端:

public static void main(String[] args) throws UnknownHostException, IOException {
		Socket s = new Socket("127.0.0.1", 10006);
		BufferedInputStream bufin = new BufferedInputStream(new FileInputStream("test.png"));
		BufferedOutputStream out = new BufferedOutputStream(s.getOutputStream());
		int len = 0;
		byte[] buf = new byte[1024];
		while((len = bufin.read(buf))!= -1){
			out.write(buf, 0, len);
			out.flush();
		}
		s.shutdownOutput();
		BufferedInputStream in = new BufferedInputStream(s.getInputStream());
		len = in.read(buf);
		System.out.println(new String(buf, 0, len));
		bufin.close();
		s.close();
	}

服务端:

public static void main(String[] args) throws UnknownHostException, IOException {
		Socket s = new Socket("127.0.0.1", 10006);
		BufferedInputStream bufin = new BufferedInputStream(new FileInputStream("test.png"));
		BufferedOutputStream out = new BufferedOutputStream(s.getOutputStream());
		int len = 0;
		byte[] buf = new byte[1024];
		while((len = bufin.read(buf))!= -1){
			out.write(buf, 0, len);
			out.flush();
		}
		s.shutdownOutput();
		BufferedInputStream in = new BufferedInputStream(s.getInputStream());
		len = in.read(buf);
		System.out.println(new String(buf, 0, len));
		bufin.close();
		s.close();
	}

验证结果:







e,字符流的文件上传

客户端:

public static void main(String[] args) throws UnknownHostException, IOException {
		Socket s = new Socket("192.168.1.3", 10007);
		BufferedReader bufr = new BufferedReader(new FileReader("ReadIn.java"));
		PrintWriter out = new PrintWriter(s.getOutputStream(),true);
		String line = null;
		while((line = bufr.readLine())!= null){
			out.println(line);
		}
		/*
		 * 传文件时,需要分析是否是文本,最主要的的一点需要关闭流
		 * shutdownOutput,否则服务器无法识别什么时候结束
		 * */
		s.shutdownOutput();
		BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
		line = in.readLine();
		System.out.println(line);
		bufr.close();
		s.close();
	}

服务端:

public class servDemo4 {

	public static void main(String[] args) throws IOException {
		getserve();
	}
	public static void getserve() throws IOException{
		ServerSocket ss = new ServerSocket(10007);
		while(true){
			Socket s = ss.accept();
			new Thread(new serv(s)).start();
		}
	}

}
class serv implements  Runnable{
	private Socket s;
	private static int count = 0;
	public serv(Socket s) {
		this.s = s;
	}

	public void run() {
		PrintWriter pw = null;
		try {
			String ip = s.getInetAddress().getHostAddress();
			System.out.println(ip+".....connetion");
			BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
			pw = new PrintWriter(new FileWriter(ip+"("+(count++)+")"),true);
			String line = null;
			while((line = in.readLine())!= null){
				pw.println(line);
			}
			PrintWriter out = new PrintWriter(s.getOutputStream(),true);
			out.println("用户ip为"+ip+"的文件上传成功");
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			System.out.println(e.toString());
		}finally{
			pw.close();
			try {
				s.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				System.out.println(e.toString());
			}
		}
	}
}

验证结果:



5,TCP和UDP总结:

/*
 * 1,常见的阻塞式方法:
	IO流中的BufferedReader的readLine()方法
	IO流中的InputStream的read(byte[])方法
	UDP通信中的接收方的receive(Datagrampacket)方法
	TCP通信中的服务器方的accept()方法
 * 2,双卡现象分析
 * 情况一:读取行时,没有添加newline()和flush()方法,导致另一方无法读行结束符,使用PrinterWriter就能解决情况一
 * 情况二:读取整个文本时,读到文件结尾,返回的是EOF标记,客户端无法有效的关闭流,所以在while结束时,添加shutdownOutput,就可以
 * 3,流的个数:
 * 一般情况下客户端需要三个流以上,两个网络流封装在socket中,本地流挑选其一,
 * 服务端需要至少两个流,网络流即可,处理客户端的数据,如果要存储和读取本地文件,则需要根据功能需求加入本地流
 * 规律:
 * 本地流:	BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
 * 			BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(system.out()));
 * 			(System.setin(键盘,内存,硬盘),System.setout(显示器,内存,硬盘))
 * 网络流:	PrintWriter out = new PrintWriter(s.getOutputStream(),true);//文件操作加true,
			BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
 * */


 ----------android培训java培训、java学习型技术博客、期待与您交流! -----------

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值