一个最简单的网络编程
今天总结一下,我至今学的第一个网络编程,也是一个最简单的网络编程。
这篇博客只是将如何用代码实现一个网络编程,具体细节不讲解,后续会介绍详细细节。
网络编程会涉及到客户端和服务器的实现。
1.服务器的实现
首先,服务器的接受请求和发送响应的功能,我们通过DatagramSocket类的实例化对象来实现,一般对于服务器,我们一般希望服务器有一个固定的端口号,所以在创建DatagramSocket对象时,一般会固定一个端口号。
接着,我们在一个start方法中具体实现服务器的功能。
首先,我们需要一个UDP数据包来保存客户端发送来的请求,这个UDP数据报可以通过DatagramPacket类来实现。
如上图,requestPacket就是来保存客户端发送来的请求,请求的具体内容是保存在构造方法中的byte数组中,注意,此时请求的内容还没有保存到byte数组里面,我们只是构造了一个保存请求内容的载体,还未初始化。
接着通过socket对象的receive方法来接受客户端发送来的请求。
这里receive方法中的requestPacket是一个返回型参数,则经过该方法后,requestPacket的byte数组已经初始换完成了。
注意:当服务器没有接受到客户端发送来的请求时,时会阻塞在receive方法这里的。
接着,接受到客户端发送来的请求之后,我们就要解析请求中的内容。
由于在网络中,数据的发送都是将数据转换为二进制来发送,这里我们就是将二进制还原成字符串。
这里的requestPacket.getData方法是获取保存请求内容的byte数组,而 requestPacket.getLength方法可以获取到byte数组中的有效长度。
再接着,我们就要对请求进行响应,由于,我们这里实现的是回显型服务器,所以请求和响应是相同的,相当于这步骤省略了。
再接着,我们就要将响应返回给客户端,此时,我们也要建立一个UDP数据报来存储响应,不过在建立响应的数据报的时候,由于UDP数据报没有保存对端的ip地址和端口号,所以我们要将目的IP和目的端口号明确,因为服务器返回响应时,我们要明确将响应返回到哪一个客户端。
接着将响应数据包发送给客户端,也就是返回响应,通过send方法来实现。
最后,我们来打印请求内容和响应内容
getAdress方法用来获取ip地址,getPort方法用来获取端口号。
服务器完整代码实现
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;public class UdEchoServer {//通过socket对象来实现接受请求和发送响应DatagramSocket socket=null;public UdEchoServer(int port) throws SocketException {//port是服务器的固定端口号socket=new DatagramSocket(port);}public void start() throws IOException {System.out.println("服务器启动");while(true){DatagramPacket requestPacket=new DatagramPacket(new byte[4096],4096);socket.receive(requestPacket);String request=new String(requestPacket.getData(),0, requestPacket.getLength());String response=process(request);DatagramPacket responsePacket=new DatagramPacket(response.getBytes(),0,response.getBytes().length,requestPacket.getSocketAddress());socket.send(responsePacket);System.out.printf("[%s, %d] request: %s, response: %s\n",requestPacket.getAddress().toString(),requestPacket.getPort(),request,response);}}private String process(String request) {return request;}public static void main(String[] args) throws IOException {UdEchoServer server=new UdEchoServer(9090);server.start();}
}
2.客户端的实现
首先,客户端的作用就是向服务器发送请求和接收服务器返回的响应,所以,我们也是要通过DatagramSocket类的实例化对象来实现发送和接受功能。
不过此时数据通过UDP数据报来发送和接收的,而UDP是不保存对端的IP和端口号,所以此时我们可以在客户端的代码中记录服务器的IP和端口号。
还有对于客户端,我们希望客户端的端口号是随机的。
接下来,我们也在一个start方法里面实现客户端中的具体功能。
首先,需要设计一个用户输入请求的功能。
然后再建立一个DatagramPacket对象(UDP数据报)来保存请求的内容,在建立这个UDP数据报时,我们也要明确对端IP和对端的端口号。
InetAddresss.getByName()方法将IP地址转换为。
接着,存储好数据后就要将请求发送给服务器,通过send方法来实现。
在接着就要读取服务器的响应,并解析出响应的内容。
这一步,我们还要创建一个DatagramPacket对象来保存响应的内容,并通过receive方法来接收服务器的响应和初始化DatagramPacket对象。
最后打印响应的内容
客户端完整代码
import java.io.IOException;
import java.net.*;
import java.util.Scanner;public class UdEchoClient {DatagramSocket socket=null;public String serverIp;//客户端端IP地址public int serverPort;//客户端端口号public UdEchoClient(String serverIp,int serverPort) throws SocketException {this.serverIp=serverIp;this.serverPort=serverPort;socket=new DatagramSocket();//不传参,会随机分配一个端口号给客户端}public void start() throws IOException {Scanner scanner=new Scanner(System.in);while (true){System.out.println("请输入你的请求内容");String request=scanner.next();DatagramPacket requestPacket=new DatagramPacket(request.getBytes(),request.getBytes().length,InetAddress.getByName(serverIp),serverPort);socket.send(requestPacket);DatagramPacket responsePacket=new DatagramPacket(new byte[4096],4096);socket.receive(responsePacket);String response=new String(responsePacket.getData(),0,responsePacket.getLength());System.out.println(response);}}public static void main(String[] args) throws IOException {UdEchoClient client=new UdEchoClient("127.0.0.1",9090);client.start();}
}
运行代码