Java编程TCP和UDP

本文深入对比了TCP与UDP两种网络传输协议的区别,包括面向连接与否、包头大小、传输模式等,并提供了创建客户端和服务端的具体Java代码实例。适用于理解网络编程基础知识。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.区别:
TCP 面向连接;UDP 不建立可靠连接
TCP 信息包头 20 个字节;UDP 8 个字节
TCP 只能一对一的传输;UDP 支持一对一、一对多、多对一、多对多的传输
TCP 需要维护连接状态;UDP 无
TCP 拥有流量控制及拥塞控制的机制;UDP 不关注网络状况
TCP 通过流模式传输数据;UDP 通过数据报模式传输数据
TCP 保证数据正确性、不丢包、不重复、有序性;UDP 只最大交付,不保证可靠性
TCP 适合网络负担不大、可靠性要求高的场景;UDP 适合网络负担重响应高、客户端较多、可靠性要求不高的场景
 

2.1 使用tcp创建一个客户端

package com.socket;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;

public class LoginClient {
	public static void main(String[] args) {
		OutputStream os=null;
		Socket socket=null;
		try {
			//表示建立一个tcp的客户端  1参表示发送地址,2参表示发送端口
			socket=new Socket("localhost", 8800);
			//发送信息要借助什么? 给服务器发送的信息。定义发送信息
			String info="服务器你好!";
			//通过socket对象获取到字节输出流
			os=socket.getOutputStream();
			//将信息发送给服务器。wirte发送的是字节。所以要string转为byte
			os.write(info.getBytes());
            //关闭发送端
            socket.shutdownOutput();
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			try {
				os.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
			try {
				socket.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

2.2 使用tcp创建一个服务端

package com.socket;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class LoginServer {
	public static void main(String[] args) {
		BufferedReader br=null;
		InputStream is=null;
		Socket socket=null;
		ServerSocket ss=null;
		try {
			//表示创建一个tcp服务端  端口号是8800  用于接收用户的信息 
			ss=new ServerSocket(8800);
			//使用tcp服务端 接收方法 来接收请求 返回的就是一个socket  
			socket=ss.accept();
			//socket获得读取的字节内容
			is=socket.getInputStream();
			//创建字符流对象   需要InputStreamReader(这里写入is对象)
			br=new BufferedReader(new InputStreamReader(is));
            //定义一个字符串 用来接收数据
			String info;
			while((info=br.readLine())!=null) {
				System.out.println("客户端发送的信息是"+info);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			try {
				socket.close();
				br.close();
				ss.close();
				is.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
			
		}
	}
}

3. 1 使用tcp和线程传输对象 (创建服务端)

package com.threadsocket;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class LoginServer {
	public static void main(String[] args) {
		try {
                        //创建tcp服务端
			ServerSocket ss=new ServerSocket(8802);
                        //一直保持服务端处于获取状态
			while(true) {
                                //tcp服务端获取数据方法
				Socket socket=ss.accept();
                                //线程构造函数,传入一个 socket获取
				LoginThread lt=new LoginThread(socket);
				new Thread(lt).start();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}
}

3.2 使用tcp和线程传输对象(创建客户端)

package com.threadsocket;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class LoginClient1 {
	//使用多线程 模拟多个用户登录  
	//多个用户就是多个客户端 
	//服务器只有一个  必须让服务器一直处于开启状态  或者说监听状态 
	//写一个线程类用户处理客户端的请求  
	public static void main(String[] args) {
		try {
			Socket socket=new Socket("localhost",8802);
			Stu stu=new Stu("赵四", "6666");
			OutputStream os=socket.getOutputStream();
			ObjectOutputStream  oos=new ObjectOutputStream(os);
			oos.writeObject(stu);
			oos.flush();
			oos.close();
			os.close();
			socket.close();
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

3.3 创建线程(用于服务端调用)

package com.threadsocket;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.net.Socket;
public class LoginThread implements Runnable{
	//为了区分不同的socket  
	private Socket socket;
        //创建构造函数,传入socket参数
	public LoginThread(Socket socket) {
		this.socket = socket;
	}
	@Override
	public void run() {
		try {
                        //用传入的socket获取字节流
			InputStream is= socket.getInputStream();
			ObjectInputStream ois=new ObjectInputStream(is);
			Stu stu=(Stu) ois.readObject();
			System.out.println("服务器获取到客户端发送的信息"+stu);
			ois.close();
			is.close();
			socket.close();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
}

UDP发送数据Dome

1.使用udp创建客户端

package com.udp.DatagramSocket;

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

public class LoginClient {
	//tcp是面向连接的
	//udp是非面向连接的
	public static void main(String[] args) {
		try {
			//建立udp客户端
			DatagramSocket ds=new DatagramSocket();
			//发送消息的内容  数据大小  数据地址  端口号
			String info="卢你好";
			byte[] b=info.getBytes();//字符串转为字符型数组
			//发送到的地址名
			InetAddress ia=InetAddress.getByName("10.8.165.31");
			//把数据打包
			DatagramPacket dp=new DatagramPacket(b, b.length, ia, 8802);
			
			//把数据发送
			ds.send(dp);
			//定义接收数据的大小
			byte[] newb=new byte[1024];
			DatagramPacket newdp=new DatagramPacket(newb, newb.length);
                        //接收数据,并没有返回值
			ds.receive(newdp);
			//因为没有返回值,需要用new String输出包中的数据,可以在此设置字符集
			System.out.println("服务端发送的是"+newString(newdp.getData(),0,newdp.getData().length));
			System.out.println("服务端发送的数据是"+new String(newdp.getData(), "utf-8"));
			
			ds.close();
		} catch (SocketException e) {
			e.printStackTrace();
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

1.2使用udp创建服务端

package com.udp.DatagramSocket;

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

public class LoginServer {
	public static void main(String[] args) {
		try {
			//udp的传输方式 建立udp服务端
			DatagramSocket ds=new DatagramSocket(8899);
			//接受数据之前。需要建立数据的大小。
			byte[] datas=new byte[1024];
			//因为数据是非面向连接的。所以数据是以包的形式打包接收的。数据的包名。和数据的大小
			DatagramPacket dp=new DatagramPacket(datas, datas.length);
			//接收的方法名。没有返回值
			ds.receive(dp);
			//因为没有返回值。所以使用String方法。1.得到该数据 2.从第几个数据开始。长度为字节 3.数据的长度。
			System.out.println("接收到的数据是"+new String(dp.getData(), 0, dp.getData().length));
             //服务端收到数据后 向发送端回复数据
			byte[] b="你好 客户端".getBytes();
			//getSocketAddress  用来获取客户端发来包的地址
			SocketAddress address=dp.getSocketAddress();  
			DatagramPacket dgp=new DatagramPacket(b, b.length, address);
			//发送方法
			ds.send(dgp);
			
		} catch (SocketException e) {
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值