问题引出
java的输入/输出流很神奇,虽然write()的参数类型可以是int(32bit),但是实际上传的数据只能是byte(8bit),如果前行传int,那么,只会传最低的8位。
同理,其他数据类型也是如此。例如中文,或是长英文
int类型
思路就是,把一个int拆成四个byte,传过去之后,再拼起来。
public void sendInt(int value){
OutputStream os= null; //这里是用socket的输出流,而不是用serversocket的
try {
os = socket.getOutputStream();
int b24=(value>>24)&0xFF;
int b16=(value>>16)&0xFF;
int b8=(value>>8)&0xFF;
int b0=(value>>0)&0xFF;
os.write(b24);
os.write(b16);
os.write(b8);
os.write(b0);
os.flush();
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public void receiveInt(){
int vel=0;
try {
InputStream is = client.getInputStream();
int[] msg=new int[4];
System.out.println("开始读消息:");
for (int i=0;i<4;i++){
msg[i]=is.read();
}
for (int i=0;i<4;i++){
vel=vel+msg[i]<<(3-i)*8;
}
System.out.println(vel);
client.close();
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
String类型
同样的,传输string又会遇到上面那个问题,,,,resd()\write()只能读写最后8位。
解决办法:
把string拆成一个byte[]传过去,再用一个byte[]接收。
当然,由于新建接收所需的byte[]时,需要长度。所以发送时,也要发送byte[]的长度。
接收时,可以使用read(byte[] b),将输入流存到b中。也可以用read()配合循环,将输入流输入到byte[]中。
String(byte[] b)能自动将byte[]拼成字符串。
字符串中,英语占一个byte,而汉字一般占2个字节(根据编码不同,所占大小也不同,比如utf-8,一个汉字可占2,3,4个字节)。
public void sendSring(String msg){
int len=msg.getBytes().length;
OutputStream os= null;
try {
if (len>255){
System.out.println("字数限制在255以内");
}else {
os = socket.getOutputStream();
os.write(len); //这个len最大值只能传255
//根据源码注释,这里会将String类型转为byte[],然后进行输出
os.write(msg.getBytes());//这里write两个,所以客户端要read两次
os.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
public void receiveString(){
try {
InputStream is = client.getInputStream();
int len=is.read();
byte[] bytes=new byte[len];
is.read(bytes);//从输入流中读取到bytes中,具体见源码注释
String msgStr=new String(bytes);
System.out.println(msgStr);
} catch (IOException e) {
e.printStackTrace();
}
}
这种方法有个问题,因为需要传len,也类似传整数时遇到的问题,len转成byte后,最大值时255。所以,字符串发送长度最大是255,这也就是微博,推特限制字数的原因。
当然,传len时,调用前面传长整数的方法就可以解决这个问题。
发送图片
这个的重点是如何提高图片的发送速度。
先将图片装入一个bety[],再发送这个bety[]。要避免每个像素单独发送,这样cpu会在计算和io之间频繁切换,速度慢
项目地址:v1