基于套接字的连接:原理、操作与应用示例
立即解锁
发布时间: 2025-08-18 02:20:35 阅读量: 1 订阅数: 5 

# 基于套接字的连接:原理、操作与应用示例
## 1. 套接字连接基础
套接字是实现两个系统之间通信的一种方式,它能将网络连接视为一个流。一旦套接字建立,就可以使用`InputStream`从流中读取数据,或使用`OutputStream`向流中写入数据。
### 1.1 通用连接框架接口
通用连接框架提供了两个用于处理流的接口:
- `StreamConnectionNotifier`:服务器使用它来监听端口,等待客户端建立连接。
- `StreamConnection`:用于建立套接字连接。
`StreamConnection`接口同时扩展了`InputConnection`和`OutputConnection`,允许在单个连接上进行读写操作。
### 1.2 建立连接步骤
#### 1.2.1 服务器端
服务器端需要先绑定到指定端口,使用`StreamConnectionNotifier`的示例代码如下:
```java
StreamConnectionNotifier connection = (StreamConnectionNotifier)
Connector.open("serversocket://:4444", Connector.READ_WRITE);
```
上述代码中,`serversocket`方案告诉`Connector`打开一个`StreamConnectionNotifier`,端口号在地址部分的`:`后面指定。一旦建立了`StreamConnectionNotifier`,服务器就会使用`acceptAndOpen()`方法等待客户端连接:
```java
StreamConnection sc = connection.acceptAndOpen();
```
#### 1.2.2 客户端
客户端通过直接打开`StreamConnection`来连接到套接字监听器,示例代码如下:
```java
StreamConnection connection = (StreamConnection)
Connector.open("socket://127.0.0.1:4444", Connector.READ_WRITE);
```
客户端需要在地址部分指定主机和端口号,并且端口号必须与服务器端一致,否则无法建立连接。
### 1.3 连接建立后的操作
连接成功后,客户端和服务器端都可以开始读写数据。通常,客户端会先向流中写入数据,但这不是套接字的强制要求。
## 2. 向套接字写入数据
连接成功后,可以使用`StreamConnection`的`openOutputStream()`或`openDataOutputStream()`方法获取输出流:
```java
OutputStream os = connection.openOutputStream();
DataOutputStream os = connection.openDataOutputStream();
```
获取输出流后,应用程序可以使用`OutputStream`的各种方法开始写入数据。为了方便处理,可以将`OutputStream`包装在其他流类中,例如`OutputStreamWriter`,它可以处理基于字符的流内容:
```java
OutputStreamWriter osw = new OutputStreamWriter(os);
```
### 2.1 相关输出流类
| 类名 | 说明 |
| ---- | ---- |
| `OutputStream` | 提供写入字节数据、刷新流和关闭流的基本方法,其他输出流类要么扩展它,要么包装它的实例。 |
| `DataOutput` | 定义将原始数据类型(如`int`、`long`、`boolean`等)转换为字节数组的方法,还能将Java字符串转换为UTF - 8格式。 |
| `DataOutputStream` | 扩展`OutputStream`并实现`DataOutput`接口,以独立于机器的方式处理字节、字符和UTF编码的数据。 |
| `ByteArrayOutputStream` | 扩展`OutputStream`,为写入字节流提供动态缓冲功能,提供`toByteArray()`和`toString()`方法来检索数据。 |
| `Writer` | 抽象类,支持写入基于字符的流,Java使用`java.io`包中的`Writer`命名约定来表示作为字节流和基于字符的流之间桥梁的类。 |
| `OutputStreamWriter` | 扩展`Writer`,为应用程序提供向输出流写入字符的实现,除了`write()`方法外,通过该类写入流的所有字符都会被缓冲,需要调用`flush()`方法将数据实际写入流。 |
| `PrintStream` | 方便类,扩展`OutputStream`,提供轻松打印流数据的方法,`println()`方法会自动在打印的数据末尾添加换行符,并且不抛出`IOException`,而是设置内部标志,可通过`checkError()`方法检查错误状态。 |
### 2.2 写入数据示例
```java
// 写入UTF-8编码的字符串
String data = "Test Message";
os.writeUTF(data);
os.flush();
// 写入字节数组
byte[] b = data.getBytes();
os.write(b, 0, b.length);
os.flush();
```
## 3. 从套接字读取数据
从套接字读取数据的API与写入数据的API类似,但执行读取操作。获取输入流后,可以使用一些类来帮助从流中检索数据。
### 3.1 相关输入流类
| 类名 | 说明 |
| ---- | ---- |
| `InputStream` | 提供从流中读取字节数据和关闭流的基本方法,其他输入流类要么扩展它,要么包装它的实例。 |
| `DataInput` | 定义读取字节流并将字节序列转换为Java原始数据类型(如`int`、`long`、`short`、`char`、`boolean`等)的方法,还能从UTF - 8格式创建Java字符串。 |
| `DataInputStream` | 扩展`InputStream`并实现`DataInput`接口,提供从输入流中的字节序列读取和转换Java原始数据的实现,还能以独立于机器的方式处理UTF编码的数据。 |
| `ByteArrayInputStream` | 扩展`InputStream`,在从字节输入流读取时提供缓冲功能,读取的字节数由构造函数提供的缓冲区大小决定。 |
| `Reader` | 抽象基类,Java使用`java.io`包中的`Reader`命名约定来表示作为字节流和基于字符的流之间桥梁的类,使用`Reader`的主要好处是在读取操作期间会自动将数据的字节表示转换为字符表示。 |
| `InputStreamReader` | 扩展`Reader`,提供从字节流读取字符数据的实现,在字节和字符数据之间提供一层转换,还能返回UTF编码的数据,自动支持缓冲,每次读取操作都会从流中实际读取一个或多个字节。 |
### 3.2 读取数据示例
```java
// 读取UTF-8编码的字符串
String dataIn = is.readUTF();
// 读取字节并转换为字符串
int ch = 0;
StringBuffer sb = new StringBuffer();
while (ch != -1) {
ch = is.read();
if (ch == -1) {
break;
}
sb.append((char)ch);
}
String dataIn = sb.toString();
```
## 4. 何时使用套接字
套接字是连接两个系统并交换数据的一种原始但轻量级的方法,由于其开销低,可能是两个系统之间交换数据和发出命令最快的方法之一。然而,套接字的轻量级特性意味着需要定义两个系统之间的通信协议。
### 4.1 适用场景
- **速度优先**:当速度比遵循开放协议标准更重要时,使用套接字可能意味着实现一种专有的数据传输机制。例如,HTTP协议也可以使用套接字实现。
- **结合其他协议**:套接字仅提供传输机制,可以与其他数据格式或协议结合使用,如XML。但这需要客户端和服务器应用程序之间的协调,因为它们都需要支持相同的连接类型。
### 4.2 不适用场景
如果系统需要遵循开放通信标准,或者无法控制客户端和服务器两端,套接字可能不是实现通信功能的好方法,此时使用HTTP等协议可能更合适。
## 5. 客户端 - 服务器套接字示例
### 5.1 修改客户端
在`MsgClient`应用程序中加入套接字功能,需要进行以下两步修改:
- **添加菜单选项**:在菜单选项列表中添加“Socket Message”。
```java
private static final String[] choices = {
"1 HTTP Example",
"2 Socket Message"
};
```
- **增强`handleOK()`方法**:当选择“Socket Message”菜单选项时,调用`socketMessage()`方法。
```java
private void handleOK(int idx) {
display.setCurrent(outputForm);
switch (idx) {
```
0
0
复制全文
相关推荐










