更新时间:2022-06-21 12:36:21 来源:极悦 浏览1188次
客户端和服务器是套接字编程的两个主要组件。客户端是请求服务的计算机/节点,服务器是响应客户端的计算机/节点。在 Java 中,使用套接字编程,我们可以连接客户端和服务器。
套接字是用于发送和接收消息的端点。它是 IP 地址和端口号的组合。客户端-服务器程序中使用了两种类型的套接字:一种是客户端套接字,另一种是服务器套接字。在客户端-服务器程序中,客户端必须知道客户端想要发送服务请求的服务器端点的位置(IP 地址和端口号)。在计算机世界中,客户端和服务器都是应用程序。服务器程序使用服务器套接字,而客户端程序使用客户端套接字进行通信。
以下 Java 程序说明了如何在客户端和服务器之间建立通信。让我们从客户端程序开始。
// 导入语句
导入java.net.*;
导入java.io.*;
导入 java.util.Scanner;
公共类客户端
{
// 初始化套接字和输入输出流
私有数据输出流数据输出 = null;
私人扫描仪 sc = null;
私有套接字 skt = null;
// 构造函数来创建具有给定 IP 和端口地址的套接字
公共客户端(字符串地址,int 端口)
{
// 与服务器建立连接
尝试
{
// 创建一个socket对象
skt = 新套接字(地址,端口);
System.out.println("连接建立!!");
System.out.println("输入 \"Finish\" 终止连接。");
// 从用户那里获取输入
sc = 新扫描仪(System.in);
// 在套接字上打开输出流
dataOut = new DataOutputStream(skt.getOutputStream());
}
catch(UnknownHostException 呃)
{
System.out.println(uh);
}
捕捉(IOException io)
{
System.out.println(io);
}
// 存储用户输入的信息
字符串 str = "";
// 继续读取直到输入“Finish”
而(!str.equals(“完成”))
{
输入 = sc.nextLine(); // 读取输入
尝试
{
dataOut.writeUTF(str); // 写入底层输出流
}
// 用于在写入输出流时处理错误
捕捉(IOException io)
{
System.out.println(io);
}
}
System.out.println("连接终止!!");
// 用于关闭连接
尝试
{
数据输出.close();
skt.close();
}
捕捉(IOException io)
{
System.out.println(io);
}
}
公共静态无效主要(字符串argvs [])
{
// 创建类Client的对象
ClientSide client = new ClientSide("localhost", 6666);
}
}
解释:我们知道要建立连接,客户端和服务器端都需要套接字。以下语句在客户端创建一个套接字:
sk = 新套接字(地址,端口);
Socket 类的构造函数有两个参数:一个是地址(IP 地址),另一个是端口(端口号),并创建了 Socket 类的对象。在代码中,我们使用了端口号 6666。这里,我们使用了 localhost,因为客户端应用程序和服务器应用程序运行在同一个系统上。通常,客户端程序和服务器程序位于不同的系统上。在这种情况下,使用运行服务器的系统的 IP 地址而不是 localhost。确保在这种情况下使用完全限定的 IP 地址/名称。
端口号 6666 表示客户端正在尝试在端口 6666 上建立与服务器的连接。如果服务器在端口 6666 上,则连接建立;否则,不是。
该声明
dataOut = new DataOutputStream(skt.getOutputStream());
dataOut.writeUTF(str);
写入在套接字上打开的输出流。服务器正在读取输出流上写入的任何内容。这里,str是一个字符串,它读取用户输入的任何内容。变量str的读取将继续,直到用户输入“Finish”。如果在写入底层流时发生任何错误,IOException的 catch 块就会出现。
如果我们在 Socket 类的构造函数的参数中提供任何无效的 IP 地址,则上述 catch 块的以下代码片段将生效。
catch(UnknownHostException 呃)
{
System.out.println(uh);
}
例如,如果我们键入“locahost”而不是“localhost”,则上述 catch 块的语句将生效。
现在,让我们讨论一下服务器端程序。
// 导入语句
导入java.net.*;
导入java.io.*;
公共类服务器
{
//初始化输入流和套接字
私有数据输入流 inStream = null;
私有套接字 skt = null;
私有 ServerSocket srvr = null;
// 类Server的构造函数
公共服务器(int 端口)
{
// 启动服务器并等待客户端
尝试
{
srvr = 新服务器套接字(端口);
System.out.println("服务器启动");
System.out.println("正在等待客户端连接...");
skt = srvr.accept(); // 等待客户端发送连接请求
System.out.println("与客户端连接!!");
// 使用套接字接收来自客户端的输入消息
inStream = new DataInputStream(skt.getInputStream());
字符串 str = ""; // 用于读取客户端发送的消息的变量
// 直到客户端发送“完成”,
// 继续阅读消息
而(!str.equals(“完成”))
{
尝试
{
// 从底层流中读取
str = inStream.readUTF();
// 在控制台上打印读取的消息
System.out.println(str);
}
// 用于处理错误
捕捉(IOException io)
{
System.out.println(io);
}
}
//关闭已建立的连接
skt.close();
inStream.close();
System.out.println("连接关闭!!");
}
// 处理错误
捕获(IOException 我)
{
System.out.println(i);
}
}
公共静态无效主要(字符串argvs [])
{
// 创建类ServerSide的对象
服务器服务器=新服务器(6666);
}
}
解释:声明
srvr = 新服务器套接字(端口);
创建一个新套接字并将其绑定到端口号,该端口号作为参数(端口)传递给类ServerSocket的构造函数。在代码中,我们使用了端口号 6666。这意味着服务器正在侦听端口号 6666,客户端必须使用此端口号(6666)连接到服务器。
该声明
skt = srvr.accept();
服务器使用它来接受来自客户端的连接请求。服务器在调用方法accept() 后等待。等待一直持续到服务器从客户端收到连接请求。在这里,等待意味着在accept()方法之后编写的任何语句在服务器收到连接请求之前不会被执行。在这个位置,我们说服务器正在监听给定的端口号,在我们的例子中是 6666。
为了读取客户端发送的消息,我们必须打开一个到套接字的输入流。以下语句也是如此。
inStream = new DataInputStream(skt.getInputStream());
getInputStream()方法返回附加到套接字的输入流。在 Java 中,数据输出流用于写入可以稍后由输入流读取的数据。上述声明中也发生了同样的情况。当我们调用DataInputStream类的readUTF()方法时,我们从客户端发送的任何内容都会被读取。下面的语句做同样的事情
str = inStream.readUTF();
在客户端,我们使用writeUTF()方法对流进行写入部分。同样,在服务器端,我们在这里使用了 readUTF() 从流中读取部分。readUTF ()方法返回一个 Unicode 字符串,我们将其存储在变量str 中。继续阅读,直到客户端发送“完成”一词。阅读“完成”一词后,连接将关闭。下面的书面陈述达到了同样的效果。
skt.close();
inStream.close();
执行步骤
首先,应该执行服务器端程序。这是因为,当我们开始执行客户端程序时,它开始在端口号 6666 处寻找服务器。由于我们没有先执行服务器端程序,因此不会有服务器在侦听端口号 6666。因此,客户端程序引发NullPointerException。因此,客户端程序必须在服务器端程序执行之后执行。
为了执行上述程序,打开两个命令提示符,一个用于客户端程序,另一个用于服务器端程序。分别使用命令javac和java进行编译和执行。
输出:
首先,我们执行服务器端程序。
我们看到执行后,服务器等待客户端连接。现在,执行客户端程序并观察服务器如何响应。
我们看到服务器响应消息Connected with a client!! 现在,连接已经建立,我们可以向连接的服务器发送消息。观察以下快照。
1234, 78, ..., Russia 是客户端发送的输入。这些输入消息在服务器端显示。要终止连接,我们必须输入单词 Finish。
输入“完成”一词后,两边的连接都关闭了。
0基础 0学费 15天面授
Java就业班有基础 直达就业
业余时间 高薪转行
Java在职加薪班工作1~3年,加薪神器
工作3~5年,晋升架构
提交申请后,顾问老师会电话与您沟通安排学习