一个最简单的网络编程
今天总结一下,我至今学的第一个网络编程,也是一个最简单的网络编程。
这篇博客只是将如何用代码实现一个网络编程,具体细节不讲解,后续会介绍详细细节。
网络编程会涉及到客户端和服务器的实现。
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();
}
}
运行代码