首页 新闻 赞助 找找看

Socket编程write和read对应问题,发送str长度读出来有误

0
悬赏园豆:10 [待解决问题]

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方法都不可变。
请教一下,大神。万分感谢!

探知亦者的主页 探知亦者 | 初学一级 | 园豆:192
提问于:2017-01-05 21:55
< >
分享
所有回答(2)
0

客户端发送时你得告诉服务端什么时候发完,比如发完字符串再发一个/r/n表示发完了,服务端接受到这个标志符就知道已经收到一个完整的消息。

创心coder | 园豆:736 (小虾三级) | 2017-01-05 23:09
0

TCP是无论如何,只要连接还在,即使网络中断,也会在恢复的时候将未发的数据重发,除非断开时间太久,导致连接死掉了,这时候你的客户端会收到网络断开的异常。

如上所说,假如你未接到异常,那么你的数据永远和发送端是一致的。然后你需要多送多种长度及类型的数据,这时,只要求你在发送端将数据排列好容易识别,因为发送端的数据与接收端一模一样,所以,接收端如实解析便可以了。

目前用得最多的是,以一串特殊字符(如###################)为头,后面跟着四个字节表示本次发送内容的字节长度,客户端每次接收的时候,先判断是否为#,如果说,累加器加1,再接一个,直到#的数量与你设置的一致,然后再接收四个字节,转为整形,这个整形便是后面报文的总长度,此时再接收与这个整形相同长度的报文,然后解析就可以了。

需要注意的是,你要求接收多长的数据,系统不一定把你要的长度填满了才给你,而是会接收到一个分组便给你一次,所以,每次接收数据的代码执行完成后要判断实际接收了多少,然后继续接收未接收到的数据。

ensleep | 园豆:1682 (小虾三级) | 2017-01-06 09:31
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册