在这篇博文中,本人以展示网络编程的例子来为本人之后的博文做一下铺垫,同学们在学习这篇博文的时候,建议还是抱着和学习本人之前的博文——《XML 解析》和《Properties 解析》一样的态度——学习套路的方式学习这篇博文。因为本人将在之后的博文中同样地做出一个“工具”,来省略这里的步骤。那么,话不多说,开始我们这篇博文的学习吧:
那么,本人先来展示一下一个服务器 和 一个 客户之间的连接的代码:
首先,为了之后的代码方便编写,本人现来给出一个接口:
package com.mec.about_net.core;
public interface IMecNet {
int DEFAULT_PORT = 54188;
}
接下来就是 服务器 的代码:
package com.mec.about_net.server;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import com.mec.about_net.core.IMecNet;
public class SimpleServer {
private ServerSocket server;
private int port;
private DataInputStream dis;
private DataOutputStream dos;
public SimpleServer() {
this.port = IMecNet.DEFAULT_PORT;
}
public SimpleServer setPort(int port) {
this.port = port;
return this;
}
public void startup() {
try {
System.out.println("开始建立服务器……");
server = new ServerSocket(port); // 1.创建服务器
System.out.println("服务器建立成功!");
System.out.println("开始侦听客户端连接请求……");
Socket client = server.accept(); // 2.服务器等待客户端的响应,若无响应,则等待至有响应
String clientIp = client.getInetAddress().getHostAddress();
System.out.println("侦听到来自[" + clientIp + "]的连接请求,并成功连接!");
System.out.println("开始建立与客户端的通信信道……");
dis = new DataInputStream(client.getInputStream()); // 3.构建输入、输出流
dos = new DataOutputStream(client.getOutputStream());
System.out.println("已建立与客户端的通信信道!");
System.out.println("开始侦听客户端发送来的信息……");
String message = dis.readUTF(); // 4.从客户端读取信息;向客户端发出信息
System.out.println("来自客户端的消息:[" + message + "]");
dos.writeUTF("[" + message + "]");
close();
} catch (IOException e) {
e.printStackTrace();
}
}
private void close() {
try {
dis.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
dos.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
server.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
相应地,本人来给出一个这个类的Test类:
package com.mec.about_net.test;
import com.mec.about_net.server.SingleClientServer;
public class ServerTest {
public static void main(String[] args) {
new SimpleServer().startup();
}
}
那么,我们来看一下运行结果:
可以看到,运行成功了,但是,右边的红色方块,表示还处于运行状态。
本人现在来解释一下:
由于我们现在没有创建客户端,所以,其实服务器一直处于运行下行语句的状态:
Socket client = server.accept();
所以,产生了上图的结果。
那么,现在,本人来编写一个客户端的类:
package com.mec.about_net.client;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import com.mec.about_net.core.IMecNet;
public class SimpleClient {
public static final String DEFAULT_IP = "127.0.0.1"; //这里的IP地址,就是本机的IP地址
private Socket socket;
private String serverIp;
private int serverPort;
private DataInputStream dis;
private DataOutputStream dos;
public SimpleClient() {
serverIp = DEFAULT_IP;
serverPort = IMecNet.DEFAULT_PORT; //和我们上面的服务器设定一样的端口,才能保证服务器和客户端的连接
}
public SimpleClient setServerIp(String serverIp) {
this.serverIp = serverIp;
return this;
}
public SimpleClient setServerPort(int serverPort) {
this.serverPort = serverPort;
return this;
}
public void connectToServer() { //这个方法的作用是:使得客户端和服务器连接,这也是这个类的核心
try {
socket = new Socket(serverIp, serverPort);
dis = new DataInputStream(socket.getInputStream());
dos = new DataOutputStream(socket.getOutputStream());
dos.writeUTF("你好!");
String message = dis.readUTF();
System.out.println("来自服务器的消息:" + message);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
close();
}
private void close() {
try {
dis.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
dos.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
那么,上面的例子看起来还貌似还蛮简单的。
现在,本人来编写一个能够满足如下要求的程序:
只要客户端不发出“byebye”信息,服务器就一直从客户端处读取信息。
那么,本人还是先来编写服务器的类:
package com.mec.about_net.server;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import com.mec.about_net.core.IMecNet;
public class SingleClientServer {
private ServerSocket server;
private int port;
public SingleClientServer() {
this.port = IMecNet.DEFAULT_PORT;
}
public SingleClientServer setPort(int port) {
this.port = port;
return this;
}
public void startup() {
try {
System.out.println("开始启动服务器……");
server = new ServerSocket(port);
System.out.println("服务器启动成功!\n开始侦听客户端连接请求……");
Socket socket = server.accept();
String clientIp = socket.getInetAddress().getHostAddress();
System.out.println("侦听到一个客户端[" + clientIp + "]的连接请求,并已连接!");
new Thread(new Communication(socket)).start();
} catch (IOException e) {
e.printStackTrace();
}
}
class Communication implements Runnable {
private DataInputStream dis;
private DataOutputStream dos;
private volatile boolean goon;
public Communication(Socket client) {
try {
this.dis = new DataInputStream(client.getInputStream());
this.dos = new DataOutputStream(client.getOutputStream());
this.goon = true;
} catch (IOException e) {
e.printStackTrace();
}
}
public void send(String message) {
try {
dos.writeUTF(message);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
String message = null;
while (goon) {
try {
message = dis.readUTF();
System.out.println("来自客户端的消息:" + message);
if (message.equalsIgnoreCase("byebye")) {
goon = false;
} else {
send("[" + message + "]");
}
} catch (IOException e) {
if (goon == true) {
System.out.println("客户端异常掉线!");
goon = false;
}
}
}
close();
}
private void close() { //这里是关闭这个线程的方法
goon = false;
try {
if (dis != null) {
dis.close();
}
} catch (IOException e) {
} finally {
dis = null;
}
try {
if (dos != null) {
dos.close();
}
} catch (IOException e) {
} finally {
dos = null;
}
try {
if (server != null && !server.isClosed()) {
server.close();
}
} catch (IOException e) {
} finally {
server = null;
}
}
}
}
相应地,本人来给出服务器的Test类:
package com.mec.about_net.test;
import com.mec.about_net.server.SingleClientServer;
public class ServerTest {
public static void main(String[] args) {
new SingleClientServer().startup();
}
}
现在,本人来给出客户端的类:
package com.mec.about_net.client;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
import com.mec.about_net.core.IMecNet;
public class SingleClientClient {
public static final String DEFAULT_IP = "127.0.0.1";
private Socket socket;
private String ip;
private int port;
public SingleClientClient() {
this.ip = DEFAULT_IP;
this.port = IMecNet.DEFAULT_PORT;
}
public void setIp(String ip) {
this.ip = ip;
}
public void setPort(int port) {
this.port = port;
}
public void connectToServer() {
try {
socket = new Socket(ip, port);
Communication communication = new Communication(socket);
new Thread(communication).start();
Scanner in = new Scanner(System.in);
String message = "";
while (!message.equalsIgnoreCase("byebye")) { //这里检查客户端发的消息是否为"byebye",若不是,则读取下次输入 并 向服务器发送
message = in.next();
communication.send(message);
}
communication.close();
in.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
class Communication implements Runnable {
private Socket socket;
private DataInputStream dis;
private DataOutputStream dos;
private volatile boolean goon;
public Communication(Socket socket) {
try {
dis = new DataInputStream(socket.getInputStream());
dos = new DataOutputStream(socket.getOutputStream());
goon = true;
} catch (IOException e) {
e.printStackTrace();
}
}
public void send(String message) {
try {
dos.writeUTF(message);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
String message = null;
while (goon) {
try {
message = dis.readUTF();
System.out.println("来自服务器的消息:" + message);
} catch (IOException e) {
if (goon == true ) {
System.out.println("服务器异常宕机!");
}
goon = false;
}
}
close();
}
private void close() { //这里是关闭这个线程的方法
goon = false;
try {
if (dis != null) {
dis.close();
}
} catch (IOException e) {
} finally {
dis = null;
}
try {
if (dos != null) {
dos.close();
}
} catch (IOException e) {
} finally {
dos = null;
}
try {
if (socket != null && !socket.isClosed()) {
socket.close();
}
} catch (IOException e) {
} finally {
socket = null;
}
}
}
}
底下是这个类的Test类:
package com.mec.about_net.test;
import com.mec.about_net.client.SingleClientClient;
public class ClientTest {
public static void main(String[] args) {
SingleClientClient client = new SingleClientClient();
client.connectToServer();
}
}
上图表示连接成功了。
可以看到:当我们的客户端的线程向服务器发出消息时,服务器的线程会显示客户端发来的消息,并且给服务器发出回应。
上图可以看出,当我们的客户端向服务器发出“byebye”信息时,客户端正常关闭,并且在服务器这里显示客户端发来的消息,然后服务器正常关闭。
上图展示的是当我们强制关闭服务器时,客户端的反应。
上图展示的是当我们强制关闭客户端时,服务器的反应。
由于这篇博文是网络编程的基础,所以本人在这里就不进行深入的讲解了。
但是,本人之后的编程,将会大篇幅地用到这里的知识,所以,同学们不用担心这里的知识点讲得太浅。
那么,有关网络编程的基本知识点,在这里就讲解完毕了。
若是对上述知识点或代码有任何疑惑、意见或者建议,请在下方评论区提出,本人将尽早予以答复,觉得有所帮助的同学请留下小赞赞,谢谢!!!