1.客户端代码
import java.io.*;
import java.net.Socket;
public class GreetingClient {
public static void main(String[] args) throws IOException {
//准备目的地参数
String ip = "localhost";
int port=6006;
//建立工人
Socket client = new Socket(ip, port);
//建立外层管道
InputStream is = client.getInputStream();
OutputStream os= client.getOutputStream();
//建立内层数据管道
DataInputStream dis = new DataInputStream(is);
DataOutputStream ois = new DataOutputStream(os);
//输出和接收
ois.writeUTF("xxx");
System.out.println(dis.readUTF());
//关闭
client.close();
}
}
2.服务端代码写法一
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class GreetingServer extends Thread{
private ServerSocket serverSocket;
public GreetingServer(int port) throws IOException {
serverSocket = new ServerSocket(port);
serverSocket.setSoTimeout(10000);
}
public void run(){
while (true) {
Socket server= null;
try {
server=serverSocket.accept();
OutputStream os=server.getOutputStream();
InputStream is=server.getInputStream();
DataOutputStream dos = new DataOutputStream(os);
DataInputStream dis = new DataInputStream(is);
dos.writeUTF("xxx");
dis.readUTF();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws IOException {
//作为服务器端:只需准备监听端口信息
int port = 6066;
Thread t = new GreetingServer(port);//新建一个监听6066端口的线程对象,线程执行起来就是为了通信
t.start();
}
}
3.服务端写法二
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class GreetingServer2 extends Thread{
private ServerSocket serverSocket;
public void intialServerSocket(int port) throws IOException {
serverSocket = new ServerSocket(port);
}
@Override
public void run(){
while (true) {
Socket server= null;
try {
server=serverSocket.accept();
OutputStream os=server.getOutputStream();
InputStream is=server.getInputStream();
DataOutputStream dos = new DataOutputStream(os);
DataInputStream dis = new DataInputStream(is);
dos.writeUTF("xxx");
dis.readUTF();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws IOException {
GreetingServer2 G2 = new GreetingServer2();
G2.intialServerSocket(6060);
G2.start();
}
}
3.写法比较
1. 构造函数初始化
-
GreetingServer2 中,服务器套接字
ServerSocket
的初始化是在一个单独的方法intialServerSocket(int port)
中进行的,并且这个方法没有遵循Java命名规范(应为initializeServerSocket
)。这要求在创建类的实例后,还需要调用该方法来初始化服务器,这在使用上不够直观。 -
GreetingServer 则直接在其构造函数中完成了
ServerSocket
的初始化,这种方式更符合面向对象的设计原则,即对象在创建时就处于可用状态。此外,它还设置了一个超时时间setSoTimeout(10000)
,这是一个很好的实践,可以防止服务器无限期地等待连接。
2. 线程启动
- 两者都通过继承
Thread
类并重写run
方法来实现多线程服务,这是合理的。但在实际应用中,通常推荐使用Runnable
接口而不是直接继承Thread
,因为Java不支持多重继承,而实现接口可以提供更大的灵活性。不过,鉴于题目要求,这一点对比较两者不是决定性因素。
3. 异常处理与资源管理
- 两个实现中对于
Socket
的创建、输入输出流的处理以及异常捕获基本一致,但都没有很好地处理资源关闭问题,如Socket
、InputStream
、OutputStream
等资源应该在使用完毕后及时关闭,以避免资源泄露。理想情况下,应该使用try-with-resources语句或者在finally块中确保资源被关闭。
4. 可读性和简洁性
- GreetingServer 的代码结构更为简洁明了。通过构造函数初始化使得客户端代码(或主方法中的使用)更加直接,易于理解。同时,将端口号作为构造参数传递,使得该类更具通用性和可配置性。