要进行具体的网络编程,需要写一个应用程序,让这个程序实现网络通信,则需要调用传输层所提供的API.
一:UDP和TCP协议特点对比
在进行两个协议特点对比之前,我们先来了解一部分的基础知识
a:有连接 无连接
有连接:两者或者多着建立连接(以打电话为例,A给B打电话,A先必须按下电话号码,要等B按下接听才算建立连接,但如果B不在或者B不想接听,那么,此时,就相当于没有建立连接)
无连接:两者或者多着没有建立连接(以发微信/短信为例,A给B发微信,直接发过去,不需要B再进行后续操作)
在计算机中,一个客户端可以对应多个服务器,一个服务器可以对应多个客户端,同时,客户端和服务器之间存在着连接.
小tips:连接与链接的区别
链接(Link):快捷方式
连接(Connection):一个保存着另一个的信息.
b:可靠传输 不可靠传输
c:面向字节流 面向数据报
d:全双工
e:总结
二:UDP的Socket API
在学习API之前,我们先来知悉UDP中的两个核心类(DatagramSocket DatagramPacket)
a:DatagramSocket类
b:DatagramPacket类
DatagramPacket(Byte[] buf,int length) | 通过创建byte[]作为数组存储的空间,接收收据 |
DatagramPacket(byte[]buf,int offset,int length,Socket(Address address) | Ip和端口号,发送数据 |
InetAddress getAddress() | |
int getPort() | |
byte[] get Data() | 获取UDP的载荷部分(完整的应用层数据报) |
c:回显服务器
回显服务器:客户端发啥,服务器返回啥(echo server).
服务器代码:
public class UdpEchoServer { private DatagramSocket socket=null;//实现网络通信,离不开网卡,即socket对象 //创建服务器的端口号,手动指定 public UdpEchoServer(int port) throws SocketException { socket=new DatagramSocket(port); } //使用start方法启动服务器 public void start() throws IOException { System.out.println("服务器启动"); while(true){ //反复的,长期的执行针对客户端请求处理的逻辑,一个服务器,在运行过程中 //1:读取请求,并解析,通过Socket对象来调用receive来接收,并进行解析 DatagramPacket requestPacket=new DatagramPacket(new byte[4096],4096); socket.receive(requestPacket); String request=new String(requestPacket.getData(),0, requestPacket.getLength()); //2:根据请求,计算响应 String response=process(request); //3:把响应返回给客户端 //此时需要告知网卡,要发的内容是啥,发给谁 DatagramPacket responsePacket=new DatagramPacket(response.getBytes(),response.getBytes().length,requestPacket.getSocketAddress()); socket.send(responsePacket); //记录日志,打印IP地址和端口号 System.out.printf("[%s:%d] req: %s,resp %s\n",requestPacket.getAddress().toString(),requestPacket .getPort(),request,response); } } //2:根据请求,计算响应,由于是回显程序,响应内容和请求完全一样 public String process(String request){ return request; } public static void main(String[] args) throws IOException { UdpEchoServer udpEchoServer=new UdpEchoServer(1000); udpEchoServer.start(); } }
客户端代码
public class UdpEchoClient { //创建socket对象 DatagramSocket socket=null; private String serverIp;//代表服务器的IP private int serverPort;//代表服务器的端口号 //构造方法,ip代表服务器的ip,port代表服务器的端口号 public UdpEchoClient(String ip,int port) throws SocketException { serverIp=ip; serverPort=port; //创建socket对象,不再指定端口,让系统自动分配一个空闲端口 socket=new DatagramSocket(); } //启动客户端,让客户端反复从控制台读取用户输入的内容,把这个内容构造成UDP请求,发给服务器,再读取服务器的UDP返回UDP的响应 //最后再显示在客户端的屏幕上 public void start() throws IOException { Scanner scanner=new Scanner(System.in); System.out.println("客户端启动!"); while(true){ //1.从控制台读取用户输入的内容 System.out.println("->");//命令提示符 String request=scanner.next(); DatagramPacket requestPacket=new DatagramPacket(request.getBytes(),request.getBytes().length, InetAddress.getByName(serverIp),serverPort); //2将数据报发送给服务器 socket.send(requestPacket); //3.读取服务器的响应,并解析出响应内容 DatagramPacket responsePacket=new DatagramPacket(new byte[4096],4096); socket.receive(responsePacket); String response=new String(responsePacket.getData(),0,responsePacket.getLength()); //4.显示到屏幕上 System.out.println(response); } } public static void main(String[] args) throws IOException { UdpEchoClient udpEchoClient=new UdpEchoClient("127.0.0.1",9090); udpEchoClient.start(); } }
运行结果:
对于代码进行分析