1.NumberConverter.java
public interface NumberConverter {
public int toInt(byte[] b,int x,int y);
}
2.MyServer.java
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class MyServer {
private int lengthOffset;
private int lengthSize;
private int lengthAddtive;
public int getLengthOffset() {
return lengthOffset;
}
public void setLengthOffset(int lengthOffset) {
this.lengthOffset = lengthOffset;
}
public int getLengthSize() {
return lengthSize;
}
public void setLengthSize(int lengthSize) {
this.lengthSize = lengthSize;
}
public int getLengthAddtive() {
return lengthAddtive;
}
public void setLengthAddtive(int lengthAddtive) {
this.lengthAddtive = lengthAddtive;
}
public void setNumberConverter(NumberConverter numberConverter){
this.numberConverter = numberConverter;
}
private NumberConverter numberConverter = new NumberConverter(){
public int toInt(byte[] b, int i, int i_0_) {
String temp = "";
int i_1_ = 0;
for(int i_2_=0;i_2_<i_0_;i_2_++){
temp = Byte.toString(b[i+i_2_]);
if(!("32").equals(temp)){
i_1_ = i_1_*10 + ((b[i+i_2_] & 0xff) - 48);
}
}
return i_1_;
}
};
public byte[] getBytesByLength(InputStream in0,int off,int len,NumberConverter converter,int addtive) throws IOException{
DataInputStream in1 = new DataInputStream(in0);
byte[] lengthBytes = new byte[off+len];
in1.readFully(lengthBytes);
int length = converter.toInt(lengthBytes, off, len);
length+=addtive;
System.out.println("接收客户端传输的字符长度为:"+length);
return lengthBytes;
}
private byte[] resolve(InputStream in) throws IOException {
lengthOffset = 0;
lengthSize = 7;
if(lengthSize>0){
return (getBytesByLength(in, lengthOffset, lengthSize, numberConverter, lengthAddtive));
}else{
throw new IllegalArgumentException("length size must > 0");
}
}
public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket(9999);
System.out.println("我是服务器,等待客户端连接...");
Socket ssoc = null;
String sendStr = "你好,我是服务器。";
while(true){
ssoc = server.accept();
//测试--重要步骤,关键
MyServer ms = new MyServer();
ms.resolve(ssoc.getInputStream());
//读取客户端的请求信息
InputStream in = ssoc.getInputStream();
DataInputStream din = new DataInputStream(in);
String receiveStr = null;
byte[] rBuf = new byte[7];
din.read(rBuf);
receiveStr = new String(rBuf,0,7);
System.out.println("我是服务器,客户端请求的信息:"+receiveStr);
//响应客户端的请求
OutputStream out = ssoc.getOutputStream();
DataOutputStream dout = new DataOutputStream(out);
byte[] buf = sendStr.getBytes();
out.write(buf);
//关闭资源
out.close();
in.close();
ssoc.close();
}
}
}
3.MyClient.java
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class MyClient {
public static void main(String[] args) throws IOException{
Socket soc = new Socket("127.0.0.1",9999);
System.out.println("我是客户端,连接中...");
String sendStr = "<ap></ap>";
//向服务器发送消息
OutputStream out = soc.getOutputStream();
DataOutputStream dout = new DataOutputStream(out);
byte[] buf = sendStr.getBytes();
out.write(buf);
//读取服务器响应消息
InputStream in = soc.getInputStream();
DataInputStream din = new DataInputStream(in);
String receiveStr = null;
byte[] rBuf = new byte[1024];
din.read(rBuf);
receiveStr = new String(rBuf);
System.out.println("我是客户端,服务器响应的信息:"+receiveStr);
//关闭资源
in.close();
out.close();
soc.close();
}
}
疑问:System.out.println("接收客户端传输的字符长度为:"+length);接收客户端传输的字符长度为:17555239;
怎样通过修改MyClient.java,让此长度正确读取后转换为正确的字符串长度。
MyServer中resolve方法相关都不可以变更。因为这部分是框架中的内容,包括toInt方法都不可变。
请教一下,大神。万分感谢!
客户端发送时你得告诉服务端什么时候发完,比如发完字符串再发一个/r/n表示发完了,服务端接受到这个标志符就知道已经收到一个完整的消息。
TCP是无论如何,只要连接还在,即使网络中断,也会在恢复的时候将未发的数据重发,除非断开时间太久,导致连接死掉了,这时候你的客户端会收到网络断开的异常。
如上所说,假如你未接到异常,那么你的数据永远和发送端是一致的。然后你需要多送多种长度及类型的数据,这时,只要求你在发送端将数据排列好容易识别,因为发送端的数据与接收端一模一样,所以,接收端如实解析便可以了。
目前用得最多的是,以一串特殊字符(如###################)为头,后面跟着四个字节表示本次发送内容的字节长度,客户端每次接收的时候,先判断是否为#,如果说,累加器加1,再接一个,直到#的数量与你设置的一致,然后再接收四个字节,转为整形,这个整形便是后面报文的总长度,此时再接收与这个整形相同长度的报文,然后解析就可以了。
需要注意的是,你要求接收多长的数据,系统不一定把你要的长度填满了才给你,而是会接收到一个分组便给你一次,所以,每次接收数据的代码执行完成后要判断实际接收了多少,然后继续接收未接收到的数据。