当前位置: 首页> 健康> 养生 > 药品招采网站建设费用_内网进销存软件终身免费版_免费的行情软件app网站_东莞建设企业网站

药品招采网站建设费用_内网进销存软件终身免费版_免费的行情软件app网站_东莞建设企业网站

时间:2025/7/11 17:50:14来源:https://blog.csdn.net/m0_74270127/article/details/144399029 浏览次数:2次
药品招采网站建设费用_内网进销存软件终身免费版_免费的行情软件app网站_东莞建设企业网站


一、TCP流套接字编程

API介绍:

1.1 ServerSocket

ServerSocket 是创建TCP服务端Socket的API

构造方法:

构造方法描述
ServerSocket ( int  port )创建一个服务端流套接字Socket,并绑定指定端口

方法:

方法描述
Socket  accept ( )
void close ( )关闭此套接字

1.2 Socket

Socket 是客户端Socket,或服务端中接收到客户端简历连接(accept方法)的请求后,返回服务端Socket

不管是客户端还是服务端Socket,都是双方简历连接以后,保存的对端信息,及用来与对方收发数据的

构造方法:

构造方法

描述

Socket ( String host,  int port )创建一个客户端流套接字,并与对应IP主机上对应端口的进程建立连接

方法:

方法描述
InetAddress  getInetAddress( )

返回套接字所连接的地址

InputStream getInputStream( )返回此套接字的输入流
OutputStream getOutputStream( )返回此套接字的输出流

二、模拟回显服务器

public class TCPEchoServer {private ServerSocket serverSocket = null;public TCPEchoServer (int port) throws IOException {serverSocket = new ServerSocket(port); // 创建TCP 服务端Socket并绑定端口号}}

TCP是面向有连接型的,客户端要先和服务器成功建立连接才能发送数据

public class TCPEchoServer {private ServerSocket serverSocket = null;public TCPEchoServer (int port) throws IOException {serverSocket = new ServerSocket(port); // 创建 TCP 服务端Socket并绑定端口号}public void start() throws IOException {System.out.println("服务器启动!");while (true) {Socket clientSocket = serverSocket.accept();processConnection(clientSocket); // 通过这个方法处理连接}}
}

服务器启动后就要代码就会走到accept方法,如果没有客户端连接上来,accept就会阻塞,直到有客户端连接上来;客户端连接上来后,通过processConnection方法处理这个连接

private void processConnection (Socket clientSocket) throws IOException {//1. 打印一个日志,告知说当前有客户端连上了System.out.printf("[%s:%d] 客户端上线!\n", clientSocket.getInetAddress(), clientSocket.getPort());//2. 从 clientsocket 中获取流对象,来进一步的进行 后续操作try (InputStream inputStream = clientSocket.getInputStream(); OutputStream outputStream = clientSocket.getOutputStream()) {} catch (IOException e) {e.printStackTrace();} finally {clientSocket.close();}

获取到流对象后,就要从客户端的输入流中读取请求,我们可以采用inputStream.read(byte[ ] buf)的方式读取,但是读取的结果是一个byte[ ],在处理请求时还要转化为一个字符串,而且一次连接不止一个请求,一个byte[ ]里面可能有多给请求,转化为字符串后不易将不同的请求区分;所以这里采用Scanner

Scanner scanner = new Scanner(inputStream); //使用Scanner读取客户端的输入流中的数据
while (true) { //设置循环,循环读取多个请求//3.1 读取请求并解析// scanner.hasNext收到了请求且有明确的分隔符则返回trueif (!scanner.hasNext()) {  //若tcp断开则返回falseSystem.out.printf("[%s:%d] 客户端下线!\n", clientSocket.getInetAddress(), clientSocket.getPort()); //soufbreak;}String request = scanner.next(); //读取输入流中的请求}

在客户端发送的每一个情求后面都加上一个'\n',而scanner.hasNext( )就是在扫描输入流中是否还有"标记",这个标记就是指空白符(空格、制表符、换行符等),而我们每一个请求后面都会加上换行符,所以只要输入流中还有请求,循环就会继续

//3.2 根据请求计算响应
String response = process(request);
//3.3 把响应写回给客户端, 写到客户端Socket的输出流中
outputStream.write(response.getBytes(), 0, response.getBytes().length);
//3.5 服务器打印日志
System.out.printf("[%s:%d] req=%s, resp=%s\n", clientSocket.getInetAddress(), clientSocket.getPort(), request, response);

返回给客户端的响应有很多,所以每个响应的后面都要加上换行符

private String process (String request) {return request + "\n";
}

服务器完整代码:

public class TCPEchoServer {private ServerSocket serverSocket = null;public TCPEchoServer (int port) throws IOException {serverSocket = new ServerSocket(port);}public void start() throws IOException {System.out.println("服务器启动!");while (true) {//接收客户端建立连接的请求后,返回的服务端SocketSocket clientSocket = serverSocket.accept(); //客户端没有连接上来,这里就会进入阻塞processConnection(clientSocket);}}private void processConnection (Socket clientSocket) throws IOException {//1. 打印一个日志,告知说当前有客户端连上了System.out.printf("[%s:%d] 客户端上线!\n", clientSocket.getInetAddress(), clientSocket.getPort());//2. 从socket 中获取流对象,来进一步的进行 后续操作try (InputStream inputStream = clientSocket.getInputStream(); //!!!!从客户端的socket连接获取输入流和输出流OutputStream outputStream = clientSocket.getOutputStream()) {//使用Scanner读取客户端的输入流Scanner scanner = new Scanner(inputStream);//3. 也搞一个循环,针对每个连接,客户端都可能会发来多个请求,服务器也就需要返回多个响应了while (true) {//3.1 读取请求并解析//scanner.hasNext收到了请求且有明确的分隔符则返回trueif (!scanner.hasNext()) {   //若tcp断开则返回falseSystem.out.printf("[%s:%d] 客户端下线!\n", clientSocket.getInetAddress(), clientSocket.getPort()); //soufbreak;}String request = scanner.next(); //读取输入流中的请求//3.2 根据请求计算响应String response = process(request);//3.3 把响应写回给客户端, 写到客户端Socket的输出流中outputStream.write(response.getBytes(), 0, response.getBytes().length);//3.5 服务器打印日志System.out.printf("[%s:%d] req=%s, resp=%s\n", clientSocket.getInetAddress(), clientSocket.getPort(), request, response);}} catch (IOException e) {e.printStackTrace();} finally {clientSocket.close();}}private String process (String request) {return request + "\n"; //每个响应结尾加上换行符}public static void main(String[] args) throws IOException {TCPEchoServer server = new TCPEchoServer(9090);server.start();}}

接下来编写客户端代码:

public class TCPEchoClient {private Socket socket = null;public TCPEchoClient(String serverIp, int serverPort) throws IOException {socket = new Socket(serverIp, serverPort);}

上述构造方法就能和指定的服务器申请连接,然后服务器那边调用accept方法后就能成功建立连接,建立连接的过程都是操作系统内核完成的

public void start() {System.out.println("客户端启动!");Scanner scanner = new Scanner(System.in);try (InputStream inputStream = socket.getInputStream();OutputStream outputStream = socket.getOutputStream()) {Scanner scannerNetwork = new Scanner(inputStream); //读取输入流中服务器返回的响应while (true) {}} catch (IOException e) {e.printStackTrace();}
}

接下来在循环中,客户端可以不断发送请求并返回响应

//1. 从控制台读取数据
System.out.print("请输入要发送的数据: ");
String request = scanner.next(); //这个scanner只能读取控制台的数据,和输入流无关

之前约定每个请求后面都要加上换行符,这里request后面没有换行符,所以要手动加上后再写到输入流中,写入输入流就相当于将请求发送给了服务器

//2. 把请求发送给服务器
request += "\n";
outputStream.write(request.getBytes());

【疑问】为什么说这样就是将请求发送给了服务器?

【解答】在客户端程序中通过Socket的构造方法申请与服务器端建立连接,然后在服务器端程序中,通过accept方法接收了该连接,此时客户端和服务器端的两个Socket对象:socket和clientSocket,它们就是彼此关联的,通过他们的流对象就可以互相进行读写操作,比如: clientSocket的输出流对象outputStream通过write方法写入响应,socket可以通过Scanner(inputStream)读取响应,反过来也可以

//3. 从服务器读取到响应
if (!scannerNetwork.hasNext()) {break;
}
String response = scannerNetwork.next(); //scannerNetwork是扫描输入流的,和控制台无关
//4. 把响应显示到控制台上
System.out.println(response);

上述代码,服务器将相应写回到输出流中,客户端通过Scanner读取响应

完整客户端代码如下:

public class TCPEchoClient {private Socket socket = null;public TCPEchoClient(String serverIp, int serverPort) throws IOException {socket = new Socket(serverIp, serverPort);}public void start() {System.out.println("客户端启动!");Scanner scanner = new Scanner(System.in);try (InputStream inputStream = socket.getInputStream();OutputStream outputStream = socket.getOutputStream()) {Scanner scannerNetwork = new Scanner(inputStream);while (true) {//1. 从控制台读取数据System.out.print("请输入要发送的数据: ");String request = scanner.next();//2. 把请求发送给服务器request += "\n";outputStream.write(request.getBytes());//3. 从服务器读取到响应if (!scannerNetwork.hasNext()) {break;}String response = scannerNetwork.next();//4. 把响应显示到控制台上System.out.println(response);}} catch (IOException e) {e.printStackTrace();}}public static void main(String[] args) throws IOException {TCPEchoClient client = new TCPEchoClient("127.0.0.1", 9090);client.start();}}

接下来同时启动服务器程序和客户端程序:

通过控制台输入请求:


上述服务器程序中还有个问题:因为只有一个processConnection方法,所以它一次只能处理一个客户端连接,当有第二个客户端连接时,必须等到第一个客户端断开连接才能建立第二个连接,这是不合理的,所以可以引入多线程,这样可以处理多个客户端连接

Thread t = new Thread (() -> {try {processConnection(clientSocket);} catch (IOException e) {e.printStackTrace();}
});t.start();

🙉本篇文章到此结束

关键字:药品招采网站建设费用_内网进销存软件终身免费版_免费的行情软件app网站_东莞建设企业网站

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: