这两天步入java通信的学习。
首先来说一下服务器。服务器严格的讲是管理资源并为用户提供服务的计算机。通俗一点讲就是等待用户连接
并对用户发过来的信息进行处理。而客户机是连接服务器并访问服务器资料的计算机。
因此,一个简单服务器的构建步骤为:1、创建服务器对象 2、等待客户机的连入 3、一旦有客户机连入后获取
客户机的输入输出流 4、对客户机发来的数据进行处理
而一个简单的客户机的构建步骤就更为简单了:1、创建客户机对象,并连接服务器 2、用输入输出流发送数据或获取
服务器发来的数据
但是在服务器与客户机之间收发消息必须有网络协议:
1、客户机与服务器都必须了解对方发来的数据是什么样的协议并且预先知道所要处理的所有步骤
2、客户机与服务器都必须遵守协议
3、协议必须明确并无歧义
先演示一下简单的服务器(协议为以回车为结束符号的字节)
public class ServeThread extends Thread {
private java.net.Socket client;
private java.io.OutputStream out;
public ServeThread(Socket client) {
this.client = client;
}
public void run() {
dealChat(client);
}
/**
* 处理客户机发来的消息
*
* @param client
*/
private void dealChat(Socket client) {
try {
// 数据的读入和输出
out = client.getOutputStream();
java.io.InputStream ins = client.getInputStream();
DataInputStream dis = new DataInputStream(ins);
// 输入
String s = "欢迎来到游戏世界\r\n";
sendMsg(s);
String input = readString(ins);// 读入字符串
while (!input.equals("bye")) {
System.out.println("客户机说" + input);
// 将客户机发送来的内容发回客户机
s = "服务器收到" + input + "\r\n"; sendMsg(s);
input = readString(ins);// 读入字符串
}
// 客户机断开与服务器的连接
s = "欢迎下次再来";
sendMsg(s);
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 从输入流中读取的字节形成一句话返回
*
* @param ins
* 输入流
* @return 字符串
* @throws IOException
*/
private String readString(InputStream ins) throws IOException {
StringBuffer sb = new StringBuffer();// 字符缓冲区
char c = 0;
while (c != 13) {// 当未换行时
int i = ins.read();// 读取客户机发来的一个字节
c = (char) i;// 将字节转换成一个char
sb.append(c);// 将这个字符加入到字符缓冲区中
}
String inputs = sb.toString().trim();// 将字符缓冲区中的字符连成字符串
return inputs;
}
/**
* 封装发送方法
*
* @param s
* 要发送的字符串
*/
private void sendMsg(String s) {
try {
byte[] date = s.getBytes();
out.write(date);
out.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
而深入一点的是各种不同数据(如文件,消息等等)的传输,这个的话就要设计协议了,
例如
4 byte(类型) | 4 byte(整数) | a byte | ||
1(表示消息) | 消息长度 a | 消息内容 | ||
2(表示文件) | 文件名长度 a | 文件长度 b | 文件名 | 文件数据 |
4 byte(类型) | 4 byte(整数) | 4 byte(整数) | a byte | b byte |
在数据的传送接收过程中,大概来说总是会遇到这些小问题:
1、如客户机输出的消息长度为a,但是输出的消息内容却并没有达到长度a,这个就必须在客户机输出之前要进行验证,否则传送过去的数据会出错
2、服务器接收到的数据要从字节数组转换成字符串,String s=data.tostring();这样写是错误的,会直接把data数组的地址转成string,而应该改写成String s = new String(data);
3、用什么方法输出的,就必须用什么方法接收
如 用OutputStream 输出,服务器就必须用InputStream读入;用DataOutputStream输出,就要用DataInputStream读入