【黑马程序员】Java基础12:UDP和TCP的网络通讯


---------------------- ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------

二、UDPTCP各自的特点

UDPTCP传输示例

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培训、期待与您交流! ----------------------

相关内容

    暂无相关文章