1.服务器端
package socket;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerSocketTest extends Thread {
private static int count;
private static void countAdd() {
count++;
}
public static int getCount() {
return count;
}
private static ServerSocket serverSocket;
public static void startServer(int port) throws IOException {
// 1.服务器端创建ServerSocket对象,指定服务器的端口号,监听该端口,构造方法有
// 01ServerSocket(int port):指向某端口,默认该端口最多可以处理50个连接请求
// 02ServerSocket(int port,int backlog):指向某端口,指定该端口最多可以处理backlog个连接请求
// 启动服务器监听端口
serverSocket = new ServerSocket(port);
serverSocket.setSoTimeout(1000 * 60 * 10);
StringBuilder startMsg = new StringBuilder();
startMsg.append("我是服务器:" + serverSocket.getLocalSocketAddress() + "\n");
startMsg.append("我的端口号:" + serverSocket.getLocalPort() + "\n");
startMsg.append("我已启动监听服务\n");
startMsg.append("服务时长:" + serverSocket.getSoTimeout() / 60 / 1000
+ " min\n");
System.out.println(startMsg.toString());
}
public ServerSocketTest() {
}
@Override
public void run() {
while (true) {
// 2.监听端口请求
countAdd();
System.out.println("----RequestId:" + String.format("%06d", getCount())
+ "---------\n准备好监听服务...");
try {
Socket socket = serverSocket.accept();
// 休眠5秒,模仿耗时操作
Thread.sleep(5000);
StringBuilder clientHostMsg = new StringBuilder();
clientHostMsg.append("客户端主机:" + socket.getRemoteSocketAddress()
+ "\n");
clientHostMsg.append("客户端端口:" + socket.getPort() + "\n");
System.out.println(clientHostMsg.toString());
// 3.打开Socket关联的输出流/输入流通道
// 计算机之间的通信使用的是字节流,因此需要创建相应流对象
// 服务器端的输出流将用于向Socket通道写数据,数据发送到客户端
// 服务器端的输入流将用于从Socket通道读数据,数据来自客户端
DataInputStream is = new DataInputStream(socket
.getInputStream());
DataOutputStream os = new DataOutputStream(socket
.getOutputStream());
// 4.读取输入流内容
System.out.println("我是服务器,接收到客户端信息是:" + is.readUTF());
// 5.向输出流通道写入内容
String infoToClient = "小明,欢迎你连接服务器<Boss>!";
os.writeUTF(infoToClient);
// 6.关闭所有的流和套接字
is.close();
os.close();
socket.close();
}catch (InterruptedException ie) {
ie.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}
System.out.println("服务端流和套接字已关闭\n");
}
}
/**
* 1.服务器端创建ServerSocket对象,指定服务器的端口号,监听该端口
* 2.调用ServerSocket对象的accept()方法,等待客户端触发通信(即向服务器端口发送数据)
* 该方法一直被阻塞,直到客户端触发了通信,该方法给每一个客户端返回一个Socket套接字对象。 3.打开Socket关联的输出流/输入流通道
* 4.服务器读取内容自Socket套接字的数据输入通道(即输入流) 5.服务器写入内容到Socket套接字的数据输出通道(即输出流)
*/
public static void main(String[] args) throws IOException {
// 启动服务
ServerSocketTest.startServer(8080);
// 创建服务器对象
Thread serverThread = new ServerSocketTest();
// 运行服务:循环持续监听,同步阻塞式服务(单线程,多客户端请求时排队处理)
serverThread.run();
}
}
2.客户端
package socket;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
public class ClientSockerTest {
/**
* 1.客户端创建Socket连接,指定服务器的地址和端口号,请求与服务器的该端口进行连接
* 2.打开Socket关联的输出流/输入流通道
* 3.客户端写入内容到Socket套接字(指定服务器的指定端口)的数据输出通道(即输出流)
* 4.客户端读取内容自Socket套接字的数据输入通道(即输入流)
*/
public static void main(String[] args) throws UnknownHostException, IOException {
//1.客户端创建Socket连接,指定服务器的地址和端口号,请求与服务器的该端口进行连接
//Socket socket=new Socket(serverName, port)
//serverName为"服务器域名或IP地址",port为服务器服务端口号,取值0-65535
Socket socket=new Socket("localhost", 8080);
StringBuilder serverHostMsg = new StringBuilder();
serverHostMsg.append("我已连上服务端主机\n");
serverHostMsg.append("服务端主机:"+socket.getRemoteSocketAddress()+"\n");
serverHostMsg.append("服务端端口:"+socket.getPort()+"\n");
System.out.println(serverHostMsg.toString());
//2.打开Socket关联的输入和输出流通道,即在服务器的该指定端口与客户端(的某个浮动端口)之间建立数据传输通道
//计算机之间的通信使用的是字节流,因此需要创建相应流对象
//客户端的输出流将用于向Socket通道写数据,数据发送到服务器端
//客户端的输入流将用于从Socket通道读数据,数据来自服务器端
DataOutputStream os=new DataOutputStream(socket.getOutputStream());
DataInputStream is=new DataInputStream(socket.getInputStream());
//3.通过输出流/输入流通道写入/读取内容到/自服务器
//3.1向输出流通道写入内容:调用DataOutputStream的writeUTF方法
String infoToServer="我是客户端小明,请求连接服务器<Boss>...";
os.writeUTF(infoToServer);
//3.2从输入流通道读取来自服务器的响应
System.out.println("服务器<Boss>的响应是:"+is.readUTF());
//4.关闭所有流通道
is.close();
os.close();
//5.关闭套接字,服务器与客户端的所有联系通道也都被关闭
//If this socket has an associated channel then the channel is closed as well
socket.close();
System.out.println("客户端流和套接字已关闭");
}
}
3.运行效果图
