1、TCP协议的网络编程
C/S 程序即客户端与服务器程序,这是基于 TCP 协议实现的网络通信程序。
通信步骤:
- 使用 ServerSocket 搭建服务器
- 使用 Socket 搭建客户端
- 两方使用 Socket(套接字,通信端点)进行交流
2、ServerSocket
ServerSocket 类实现服务器套接字。 服务器套接字等待通过网络进入的请求。 它根据该请求执行某些操作,然后可能将结果返回给请求者。
类名: public class ServerSocket extends Object implements Closeable
常用构造方法: ServerSocket(int port)
作用:创建绑定到指定端口的服务器套接字。
常用方法:
变量和类型 | 方法名 | 描述 |
---|---|---|
Socket | accept() | 侦听对此套接字的链接并接受它,调用后程序会一直等待直到接收到为止。 |
void | close() | 关闭此套接字。 |
InetAddress | getInetAddress() | 返回此服务器套接字的本地地址。 |
int | getLocalPort() | 返回此套接字正在侦听的端口号。 |
3、Socket
Socket 类实现客户端套接字。 套接字是两台机器之间通信的端点。
类名: public class Socket extends Object implements Closeable
常用构造方法:
Socket(String host, int port)
创建流套接字并将其连接到指定主机上的指定端口号。
Socket(InetAddress address, int port)
创建流套接字并将其连接到指定IP地址处的指定端口号。
常用方法:
变量和类型 | 方法名 | 描述 |
---|---|---|
void | close() | 关闭套接字。 |
InetAddress | getInetAddress() | 返回套接字连接的地址。 |
InetAddress | getLocalAddress() | 获取套接字绑定的本地地址。 |
InputStream | getInputStream() | 返回此套接字的输入流。 |
OutputStream | getOutputStream() | 返回此套接字的输出流。 |
int | getLocalPort() | 返回此套接字绑定的本地端口号。 |
int | getPort() | 返回此套接字连接的远程端口号。 |
4、TCP通信程序案例
注意:
当 Socket 关闭后,此套接字相关的流会自动关闭,而如果此套接字相关的流先关闭会导致 Socket 也关闭(使用套接字的关闭方法除外)。
服务器代码:
package work.java.xzk10301009.comunication;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
*@ClassName: Server
*@Description: 服务器端
*
*/
public class Server {
public static void main(String[] args) throws IOException {
// 启动服务器
ServerSocket server = new ServerSocket(12345);
System.out.println("服务器已启动...");
// 等待连接,没有连接程序将一直停在这里
Socket socket = server.accept();
System.out.println("一个客户端连接了,连接信息:" + socket);
// 获取次连接套接字的输出流,并将输出流转换为打印流
PrintStream ps = new PrintStream(socket.getOutputStream());
// 向客户端发送“你好!”
ps.println("服务器:你好!");
// 获取此连接套接字的输入流,并将其转换为缓存读取流
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// 读取客户端输入的数据并打印
System.out.println(br.readLine());
// 关闭连接套接字Socket,获取的相关流也会关闭
socket.close();
System.out.println("服务器运行结束...");
}
}
客户端代码:
package work.java.xzk10301009.comunication;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.util.Scanner;
/**
*@ClassName: Client
*@Description: 用户端
*
*/
public class Client {
public static void main(String[] args) throws IOException {
// 创建客户端并连接
Socket socket = new Socket("localhost", 12345);
// 获取输入流并转换为缓存读取流
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// 读取服务器发送的一行信息并打印
System.out.println(br.readLine());
System.out.println("发送给服务器(发送后服务器将关闭):");
// 获取客户端用户输入
String text = new Scanner(System.in).nextLine();
// 获取此连接的输出流,并将其转换为打印流
PrintStream ps = new PrintStream(socket.getOutputStream());
// 向服务器输出用户输入
ps.println("客户端:" + text);
// 关闭连接
socket.close();
System.out.println("客户端运行结束...");
}
}
服务器端结果:
客户端结果:
5、多线程网络编程案例
服务器代码:
package work.java.xzk10301009.multithread;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
*@ClassName: Server
*@Description: 多线程服务器
*
*/
public class Server {
public static void main(String[] args) throws IOException {
// 创建缓存线程池
ExecutorService pool = Executors.newCachedThreadPool();
// 创建并启动服务器
ServerSocket server = new ServerSocket(12345);
System.out.println("服务器已启动...");
while (true) {
// 等待链接
Socket socket = server.accept();
// 开辟子线程响应链接
pool.execute(() -> {
// 打印链接的客户端信息
System.out.println(socket);
System.out.println(Thread.currentThread().getName() + "已连接...");
try {
// 获取输出流并转为打印流向该客户端发送消息“你好!”
PrintStream ps = new PrintStream(socket.getOutputStream());
ps.println("服务器:你好!");
String text;
while (true) {
// 一直读取客户端的消息
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
text = br.readLine();
System.out.println(Thread.currentThread().getName() + "说:" + text);
// 读到0后停止读取客户端消息
if ("0".equals(text)) {
break;
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
// 该客户端的链接线程即将结束,关闭链接
socket.close();
System.out.println(Thread.currentThread().getName() + "已断开...");
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
}
}
客户端代码:
package work.java.xzk10301009.multithread;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.util.Scanner;
/**
*@ClassName: Client
*@Description: 客户端
*
*/
public class Client {
public static void main(String[] args) throws IOException {
// 创建客户端并连接
Socket socket = new Socket("localhost", 12345);
// 获取输入流并转换为缓存读取流
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// 读取服务器发送的一行信息并打印
System.out.println(br.readLine());
String text;
Scanner input = new Scanner(System.in);
System.out.println("请任意输入(输入0即可关闭客户端):");
while (true) {
// 一直获取客户端用户输入
text = input.nextLine();
PrintStream ps = new PrintStream(socket.getOutputStream());
// 向服务器发送消息
ps.println(text);
// 当用户输入为0时停止发送消息,准备关闭客户端
if ("0".equals(text)) {
break;
}
}
// 关闭连接
socket.close();
System.out.println("客户端运行结束...");
}
}
客户端1结果:
客户端2结果:
客户端3结果:
服务器端结果: