JAVA 实现 UDP协议和TCP协议

UDP协议

UDP(User Datagram Protocol)

  • 用户数据报协议,面向无连接协议

  • 不保证可靠的数据传输

  • 速度快,可在较差网络下使用

  • 计算机通讯:数据从一个IP的port出发,运输到另外一个IP的port上

  • UDP:无连接无状态的通讯协议
    – 发送方发送消息,如果接收方刚好在目的地,就可以接受。如果不在,发送的消息就丢失了
    – 发送方也无法得知是否消息发送成功
    – UDP的好处就是简单,节省,经济

JAVA中实现UDP协议

  • DatagramSocket类:通讯的数据管道
    sendreceive方法(对于俩边来说是双向的)
    –绑定一个IP和Port
  • DatagramPacket
    – 集装箱:封装数据
    – 地址标签:目的地IP+Port
  • 注意
    – 俩边没有主次之分
    – 接收方必须早于发起方执行
//接收方
public class UdpRecv
{
	public static void main(String[] args) throws Exception
	{
		DatagramSocket	ds=new DatagramSocket(3000); //接收方的地址,3000端口
		byte [] buf=new byte[1024];
		DatagramPacket dp=new DatagramPacket(buf,1024);//封装
		
		System.out.println("UdpRecv: 我在等待信息");
		ds.receive(dp); //接收方在等待消息,一直是阻塞的,如果有消息,数据封装在dp中
		System.out.println("UdpRecv: 我接收到信息");
		String strRecv=new String(dp.getData(),0,dp.getLength()) +
		" from " + dp.getAddress().getHostAddress()+":"+dp.getPort(); 
		System.out.println(strRecv);
		
		Thread.sleep(1000);
		System.out.println("UdpRecv: 我要发送信息");
		String str="hello world 222";
		DatagramPacket dp2=new DatagramPacket(str.getBytes(),str.length(), 
				InetAddress.getByName("127.0.0.1"),dp.getPort());
		ds.send(dp2);
		System.out.println("UdpRecv: 我发送信息结束");
		ds.close();
	}
}

//发送方
public class UdpSend
{
	public static void main(String [] args) throws Exception
	{
		DatagramSocket ds=new DatagramSocket();
		String str="hello world";
		DatagramPacket dp=new DatagramPacket(str.getBytes(),str.length(),
				InetAddress.getByName("127.0.0.1"),3000);//集装箱的地址标签
		
		System.out.println("UdpSend: 我要发送信息");
		ds.send(dp);
		System.out.println("UdpSend: 我发送信息结束");
		
		Thread.sleep(1000);
		byte [] buf=new byte[1024];
		DatagramPacket dp2=new DatagramPacket(buf,1024);
		System.out.println("UdpSend: 我在等待信息");
		ds.receive(dp2);
		System.out.println("UdpSend: 我接收到信息");
		String str2=new String(dp2.getData(),0,dp2.getLength()) +
				" from " + dp2.getAddress().getHostAddress()+":"+dp2.getPort(); 
		System.out.println(str2);
				
		ds.close();
	}
}

//输出
UdpSend: 我要发送信息
UdpSend: 我发送信息结束
UdpSend: 我在等待信息
UdpSend: 我接收到信息
hello world 222 from 127.0.0.1:3000

UdpRecv: 我在等待信息
UdpRecv: 我接收到信息
hello world from 127.0.0.1:52724
UdpRecv: 我要发送信息
UdpRecv: 我发送信息结束


注意:接收方一定要先执行,让其一直等待着数据。不然发送方发送的数据会丢失

TCP协议

TCP:Transmission Control Protocol

  • 传输控制协议,面向连接的协议
  • 俩台机器的可靠无差错的数据传输
  • 双向字节流传递(双方可同时发送数据)

JAVA 中TCP协议

服务器是实现一定的功能,必须在一个公开地址对外提供服务

TCP实现步骤:

  • 服务器:创建一个ServerSocket,等待通讯
  • 客户机:创建一个Socket,连接到服务器
  • 服务器:ServerSicket接收到连接,创建一个Socket和客户的Socket建立一个专线连接,后续服务器和客户机的数据传输(一对Socket)会在一个**单独线程上(服务器建立)**运行
  • 服务器的ServerSocket继续等待连接

实现类

  • ServerSocket类:服务器码头
    – 需要绑定IP+port

  • Socket:运输通道
    – 客户端需要绑定服务器的IP和Port
    – 客户端往Socket输入流中写入数据,送到服务端
    – 客户端从Socket输出流取服务端过来的数据
    – 服务端反之亦然

  • 服务端等待响应时,处于阻塞状态

  • 服务端可以同时响应多个客户端

  • 服务端每接受一个客户端, 就启动一个独立的线程与之对应

  • 客户端和服务端都可以选择关闭这个Socket通道

  • 注意:服务端先启动,且一直保留。客户端后启动,可以先退出。

//客户端
public class TcpClient {
	public static void main(String[] args) {
		try {
			Socket s = new Socket(InetAddress.getByName("127.0.0.1"), 8001); //需要服务端先开启
			
			//同一个通道,服务端的输出流就是客户端的输入流;服务端的输入流就是客户端的输出流
			InputStream ips = s.getInputStream();    //开启通道的输入流
			BufferedReader brNet = new BufferedReader(new InputStreamReader(ips));
			
			OutputStream ops = s.getOutputStream();  //开启通道的输出流
			DataOutputStream dos = new DataOutputStream(ops);			
            //键盘的输入流
			BufferedReader brKey = new BufferedReader(new InputStreamReader(System.in));
			while (true) 
			{
				String strWord = brKey.readLine();
				if (strWord.equalsIgnoreCase("quit"))
				{
					break;
				}
				else
				{
					System.out.println("I want to send: " + strWord);
					dos.writeBytes(strWord + System.getProperty("line.separator"));
					
					System.out.println("Server said: " + brNet.readLine());
				}
				
			}
			
			dos.close();
			brNet.close();
			brKey.close();
			s.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

//服务器
public class TcpServer2
{
	public static void main(String [] args)
	{
		try
		{
			ServerSocket ss=new ServerSocket(8001);//驻守在8001端口
			while(true)
			{
				Socket s=ss.accept();  //阻塞,等到有客户端连接上来
				System.out.println("来了一个client");
				new Thread(new Worker(s)).start();//创建独立线程,如果线程过多,服务器会崩。需要例如框架来创建线程
			}
			//ss.close();
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
	}
}
class Worker implements Runnable {
	Socket s;

	public Worker(Socket s) {
		this.s = s;
	}

	public void run() {
		try {
			System.out.println("服务人员已经启动");
			//定义输入流输出流
			InputStream ips = s.getInputStream();
			OutputStream ops = s.getOutputStream();

			BufferedReader br = new BufferedReader(new InputStreamReader(ips));
			DataOutputStream dos = new DataOutputStream(ops);
			while (true) {
				String strWord = br.readLine();
				System.out.println("client said:" + strWord +":" + strWord.length());
				if (strWord.equalsIgnoreCase("quit"))
					break;
				String strEcho = strWord + " 666";
				// dos.writeBytes(strWord +"---->"+ strEcho +"\r\n");
				System.out.println("server said:" + strWord + "---->" + strEcho);
				dos.writeBytes(strWord + "---->" + strEcho + System.getProperty("line.separator"));
			}
			br.close();
			// 关闭包装类,会自动关闭包装类中所包装的底层类。所以不用调用ips.close()
			dos.close();
			s.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值