java TCP编程

发布时间:2023年12月21日

1、软件架构设计

CS架构.服务器客户端程序 优势:把一部分的计算留在客户端进行,缓解服务器压力。 劣势:如果游戏或者软件进行升级,客户端必须手动更新。 客户端:可以给服务器发送数据的软件,可以接收服务器发送过来的数据。 服务端:负责接收客户端发送过来的数据,处理数据,给客户端以响应。

BS架构.浏览器服务器架构 优势:维护成本比较低。 劣势:没办法在客户端做大量的计算。

2、Socket

Socket抽象层,相当于将传输层、网络层、链路层封装起来了,通过很简单的对象调用以及参数赋予即可实现网络通信。 极大的方便了程序的开发使用。

因为通过对计算机网络概述的了解,会发现连接只需要IP、端口号即可,其它的东西都是一成不变的。

3、客户端服务端连接

通过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("客户端连接服务器成功!!");
 ?  }
}
?

4、客户端服务端数据传输

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());
 ? ? ?  }
 ?  }
}

5、作业

  • 要求:实现一个多人聊天室。

服务端

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(); // 实现一个不停接收消息的进程
 ?  }
}

文章来源:https://blog.csdn.net/qq_64468032/article/details/135120636
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。