【黑马程序员】Java基础12:UDP和TCP的网络通讯
【黑马程序员】Java基础12:UDP和TCP的网络通讯
---------------------- ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------
二、UDP和TCP各自的特点
UDP和TCP传输示例
package blog.itheima; //编写一个多线程聊天系统,一个当作发送端,一个当作接收端 import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; class MultiThreadUDPChat { public static void main(String[] args) throws Exception{ //通过DatagramSocket对象创建udp服务;可不定义发送端口,发送时再分配 DatagramSocket sendSocker = new DatagramSocket(); //创建接收器的udp socket,建立端口 DatagramSocket recSocker = new DatagramSocket(10000); //开启发送和接收二个线程 new Thread(new Send(sendSocker)).start(); new Thread(new Rec(recSocker)).start(); } } class Send implements Runnable{ private DatagramSocket ds; //构造函数,接收一个DatagramSocket对象,即sendSocker Send(DatagramSocket ds){ this.ds = ds; } public void run() { try{ BufferedReader bf = new BufferedReader(new InputStreamReader(System.in)); String line = null; while ((line=bf.readLine())!=null){ //把从键盘录入的一行数据存储进数组中 byte[] buf = line.getBytes(); /*确定数据,并封装成数据名,发送构造方法:DatagramPacket( byte[] buf, int length, InetAddress address, int port)*/ DatagramPacket dp = new DatagramPacket(buf,buf.length, InetAddress.getByName("192.168.2.101"),10000); //数据封装好之后,发送出去 ds.send(dp); //定义结束标记 if ("886".equals(line)) break; } //ds.close();若循环发送,可不用关闭 }catch (Exception e){ throw new RuntimeException("发送信息失败"); } } } class Rec implements Runnable{ private DatagramSocket ds; Rec(DatagramSocket ds){ this.ds = ds; } public void run(){ try { //接收线程循环接收数据 while(true){ byte[] buf = new byte[1024]; /*DatagramPacket(byte[] buf, int length) 构造 DatagramPacket,用来接收长度为 length 的数据包。*/ DatagramPacket dp = new DatagramPacket(buf,buf.length); //阻塞式方法,没有数据就会等待 ds.receive(dp); //dp.getAddress() 获取IP地址封装成的对象 String ip = dp.getAddress().getHostAddress(); //getLength() 返回将要发送或接收到的数据的长度。 String data = new String(dp.getData(),0,dp.getLength()); System.out.println(ip+"---"+data); if ("886".equals(data)){ System.out.println(ip+"....离开聊天室"); break; } } }catch (Exception e){ throw new RuntimeException("接收信息失败"); } } }
package com.itheima; /** * 使用TCP协议,客户端从键盘输入读取一个字符串,发送到服务器。 * 服务器接收客户端发送的字符串,反转之后发回客户端。客户端接收并打印。 */ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; public class TcpClient { public static void main(String[] args) { //建立客户端Socket通讯服务,初始值为null Socket socket = null; try { //指定Socket的IP地址和端口,以下IP是本机地址 socket = new Socket("192.168.2.100",10000); } catch (Exception e) { System.out.println("服务器连接失败"); } //键盘录入字符 BufferedReader bufIn = new BufferedReader(new InputStreamReader(System.in)); PrintWriter out = null; //定义初始化的字符输出流 BufferedReader bufRead = null; //定义初始化的缓冲读取流 String line = null; //定义初始化的键盘录入数据,每次读一行 try { /*获取socket流中的输出流,用字符输出流写出, 加上true以后,对println、printf 或 format 可以自动刷新*/ out = new PrintWriter(socket.getOutputStream(),true); //获取socket流中的输入流,用缓冲流读取 bufRead = new BufferedReader(new InputStreamReader(socket.getInputStream())); while((line=bufIn.readLine())!=null){ //如果键盘录入的数据不为空,遍历循环 out.println(line); //将键盘录入的数据发送到服务器 //定义结束标记为over字符,放在这里可以将标记传到服务器,同时能够防止返回数据为null的情况 if("over".equals(line)) break; System.out.println(bufRead.readLine()); //打印服务器传输回来的数据 } } catch (IOException e) { System.out.println("客户端数据流传输失败"); } finally { //键盘录入和流服务最后需要关闭,不能一直占用系统资源,所以放在finally中执行 try { if(bufIn!=null) bufIn.close(); } catch (IOException e) { System.out.println("键盘录入关闭失败"); } try { if(socket!=null) socket.close(); } catch (IOException e) { System.out.println("关闭服务器连接失败"); } } } } class TcpServer{ public static void main(String[] args) { //初始化服务器 ServerSocket serverSocket = null; try { //创建服务器socket服务,并监听一个端口 serverSocket = new ServerSocket(10000); } catch (IOException e) { System.out.println("服务器建立失败"); } Socket socket = null; try { //通过accept方法获取连接过来的客户端对象,返回的是socket对象 socket = serverSocket.accept(); } catch (IOException e) { System.out.println("服务端连接客户端失败"); } BufferedReader bufr = null; //初始化缓冲读取流 PrintWriter out = null; //初始化字符输出流 StringBuilder sb = null; //初始化StringBuilder对象 String line = null; //通过socket流,得到主机IP地址 String ip = socket.getInetAddress().getHostAddress(); System.out.println("IP:"+ ip +" 用户已连接"); try { //获取socket流中的输入流,用缓冲流读取 bufr = new BufferedReader(new InputStreamReader(socket.getInputStream())); //获取socket流中的输出流,用字符输出流写出,自动刷新 out = new PrintWriter(socket.getOutputStream(),true); while((line=bufr.readLine())!=null){ //如果客户端一直有数据传输过来,那么一直循环读取 if("over".equals(line)){ //当收到客户端的over结束标记时,停止循环,不必再传输数据到客户端 System.out.println("客户端退出连接,服务器关闭"); break; } sb = new StringBuilder(line); //把客户端传输来的数据存入StringBuilder StringBuilder reverse = sb.reverse(); //利用StringBuilder的功能把字符串进行返转 out.println(reverse); //把反转后的数据传到客户端 //在服务端打印出客户端输入的数据和反转后的数据 System.out.println("客户端输入的数据为:"+line+";反转后的数据为:"+reverse); } } catch (IOException e) { System.out.println("服务器数据流传输失败"); } finally { //数据流传输和服务器最后需要关闭,不能一直占用系统资源,所以放在finally中执行 try { if(socket!=null) socket.close(); } catch (IOException e) { System.out.println("关闭客户端连接失败"); } try { if(serverSocket!=null) serverSocket.close(); } catch (IOException e) { System.out.println("服务器关闭失败"); } } } }---------------------- ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------
评论暂时关闭