CS架构.服务器客户端程序 优势:把一部分的计算留在客户端进行,缓解服务器压力。 劣势:如果游戏或者软件进行升级,客户端必须手动更新。 客户端:可以给服务器发送数据的软件,可以接收服务器发送过来的数据。 服务端:负责接收客户端发送过来的数据,处理数据,给客户端以响应。
BS架构.浏览器服务器架构 优势:维护成本比较低。 劣势:没办法在客户端做大量的计算。
Socket抽象层,相当于将传输层、网络层、链路层封装起来了,通过很简单的对象调用以及参数赋予即可实现网络通信。 极大的方便了程序的开发使用。
因为通过对计算机网络概述的了解,会发现连接只需要IP、端口号即可,其它的东西都是一成不变的。
通过ServerSocket来创建服务端对象,规定使用的端口号即可。 通过Socket对象来连接服务端,需要参数ip和端口号即可。
public class Server {
? ?public static void main(String[] args) throws IOException {
? ? ? ?// 1.创建服务器端对象
? ? ? ?ServerSocket ss = new ServerSocket(9999); // 服务端使用端口号 9999
? ? ? ?System.out.println("服务端启动成功,等待连接");
? ? ?
? ? ? ?// 2.等待客户端连接
? ? ? ?ss.accept(); // 阻塞状态,在客户端连接之前都是阻塞态,连接成功之后会继续
? ? ? ?System.out.println("客户端连接成功!!!");
? }
}
?
public class Client {
? ?public static void main(String[] args) throws IOException {
? ? ? ?// 1. 创建Socket对象
? ? ? ?Socket socket = new Socket("127.0.0.1", 9999); // 连接服务端,规定IP和端口号
? ? ? ?System.out.println("客户端连接服务器成功!!");
? }
}
?
Socket类中留的有数据传输通道,就是IO流,但仅仅是字节流,读取文本的话为了方便可以转为字符流去使用。
可以通过Socket来获取数据传输的通道,s.getInputStream(),来获取读取通道,s.getOutputStream()来获取写入通道,转为字符流之后套上BufferedReader或者BufferedWriter来使用更加的方便
而服务端中ss.accept()会等待客户端连接,连接之后返回值为Socket类,通过这个来获取socket就行。
以下程序实现的是一来一回的交互。
注意事项:除非保证写入通道不再使用,否则不要关。
public class Server {
? ?public static void main(String[] args) throws IOException {
? ? ? ?// 1.创建服务器端对象
? ? ? ?ServerSocket ss = new ServerSocket(9999);
? ? ? ?System.out.println("服务端启动成功,等待连接");
?
? ? ? ?// 2.等待客户端连接
? ? ? ?Socket s = ss.accept(); // 阻塞
? ? ? ?System.out.println("客户端连接成功!!!");
? ? ? ?Scanner sc = new Scanner(System.in);
? ? ? ?while(true){
? ? ? ? ? ?// 3.读取客户端传来的数据
? ? ? ? ? ?BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
? ? ? ? ? ?System.out.println("从客户端读取的数据为:" + br.readLine());
? ? ? ? ? ?// 4.给客户端发送一条数据
? ? ? ? ? ?BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
? ? ? ? ? ?bw.write(sc.nextLine()); // 从运行框读入字符串发送给客户端
? ? ? ? ? ?bw.newLine(); // 为了客户端方便使用Buffered,最好加上一个换行。
? ? ? ? ? ?bw.flush(); // 必须要刷新,因为传输比较麻烦,不刷新可能会丢失数据。
? ? ? }
? }
}
public class Client {
? ?public static void main(String[] args) throws IOException {
? ? ? ?// 1. 创建Socket对象
? ? ? ?Socket socket = new Socket("127.0.0.1", 9999);
? ? ? ?System.out.println("客户端连接服务器成功!!");
? ? ? ?Scanner sc = ?new Scanner(System.in);
? ? ? ?while(true) {
? ? ? ? ? ?// 2.从客户端发送数据给服务器
? ? ? ? ? ?OutputStream os = socket.getOutputStream();
? ? ? ? ? ?BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
? ? ? ? ? ?bw.write(sc.nextLine());
? ? ? ? ? ?bw.newLine();
? ? ? ? ? ?bw.flush();
? ? ? ? ? ?// 3.接收从服务端发来的信息
? ? ? ? ? ?BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
? ? ? ? ? ?System.out.println("从服务器接收的数据为:" + br.readLine());
? ? ? }
? }
}
要求:实现一个多人聊天室。
服务端
public class Server {
? ?public static void main(String[] args) throws IOException {
? ? ? ?ServerSocket ss = new ServerSocket(8989);
? ? ? ?System.out.println("服务器已经启动,等待连接中。");
? ? ? ?List<Socket> sockets = new ArrayList<Socket>(); // 用来存放所有连接服务器的用户的socket
? ? ? ?while(true){ // 保证所有想连接服务器的用户都可以正常连接
? ? ? ? ? ?Socket s = ss.accept();
? ? ? ? ? ?System.out.println("---加入了一个客户端---");
? ? ? ? ? ?sockets.add(s); // 加入用户socket列表
? ? ? ? ? ?new ServerMsgThread(s, sockets).start(); // 实现一个线程,用来接收当前socket的消息,并且发给其它所有socket,需要传参,本身socket以及socket列表,然后启动线程。
? ? ? }
? }
}
客户端
public class Client {
? ?public static void main(String[] args) throws IOException {
? ? ? ?// 1. 连接服务器
? ? ? ?Socket s = new Socket("127.0.0.1", 8989);
? ? ? ?System.out.println("连接到服务器了,可以开始聊天了。");
? ? ? ?// 2.不停的发送消息
? ? ? ?new SendMsgThread(s).start(); // 实现一个不停发送消息的进程
? ? ? ?// 3.不停的接收消息
? ? ? ?new ReceMsgThread(s).start(); // 实现一个不停接收消息的进程
? }
}