【已解决】 Socket一次传输多张图片 读取不到
用socket写了一个用传输文件的工具,可以正常传输文件,可以按文件大小写入了,第一张图片可以看,第二张开始看不到了。
接收端
package com.example.socketserivce.activity;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.telephony.mbms.FileInfo;
import android.util.Log;
import com.example.socketserivce.R;
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class ReceiveActivity extends AppCompatActivity {
public static final String TAG="ReceiveActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate (savedInstanceState);
setContentView (R.layout.activity_receive);
new Thread (){
@Override
public void run() {
startSocket();
}
}.start ();
}
private void startSocket() {
String path="/data/data/com.example.socketserivce/cache/Success-Import";
int fileNum=0;
long totalSize=0;
//接收信息
try {
File dirs1=new File (path);
Log.d (TAG, "本机地址: "+InetAddress.getLocalHost ());
if (dirs1.exists ()){
ServerSocket serverSocket=new ServerSocket (8888);
Socket socket=serverSocket.accept ();
Log.d (TAG, "成功监听到端口: ");
DataInputStream din=new DataInputStream (new BufferedInputStream (socket.getInputStream ()));
//获取文件的个数
fileNum=din.readInt ();
Log.d (TAG, "startSocket: "+fileNum);
//创建数组将文件名和文件大小保存正在其中
String[] mFileName=new String[fileNum];
long mFileSize[]=new long[fileNum];
//读取对应的文件名和文件大小
for (int i=0;i<fileNum;i++){
mFileName[i]=din.readUTF ();
mFileSize[i]=din.readLong ();
Log.d (TAG, "文件名和文件大小: "+mFileName[i]+mFileSize[i]+"个数:"+i);
}
totalSize=din.readLong ();
Log.d (TAG, "totalSize: "+totalSize);
int leftLen = 0; // 写满文件后缓存区中剩余的字节长度。
int bufferedLen = 0; // 当前缓冲区中的字节数
int writeLen = 0; // 每次向文件中写入的字节数
long writeLens = 0; // 当前已经向单个文件中写入的字节总数
long totalWriteLens=0;//写入的所有字节数
byte buf[]=new byte[8192];
for (int i=0;i<fileNum;i++){
writeLens=0;//每次循环将 当前已经写入字节数字清零
//文件写出,文件写出位置
FileOutputStream fout=new FileOutputStream ("/data/data/com.example.socketserivce/cache/Save/"+mFileName[i]);
while (true){
if (leftLen>0){//从第二个开始,当前缓冲区的字节数为leftLen
bufferedLen=leftLen;
}else{
bufferedLen=din.read (buf);
Log.d (TAG, "bufferedLen: "+bufferedLen);
}
if (bufferedLen==-1) return;
Log.d (TAG, "startSocket: "+writeLens+bufferedLen+mFileSize[i]);
if (writeLens+bufferedLen>=mFileSize[i]){
Log.d (TAG, "开始传输: "+"writeLens+bufferedLen"+(writeLens+bufferedLen)+"文件大小:"+mFileSize[i]+"buf:"+buf+"writeLen:"+writeLen);
leftLen= (int) (writeLens+bufferedLen-mFileSize[i]);
writeLen=bufferedLen-leftLen;
fout.write (buf,0,writeLen);
totalWriteLens+=writeLen;
move (buf,writeLen,leftLen);
break;
}else {
Log.d (TAG, "全部传输: ");
fout.write (buf,0 ,bufferedLen);
fout.flush ();
writeLens+=bufferedLen;
totalWriteLens+=bufferedLen;
if (totalWriteLens>=totalSize){
Log.d (TAG, "totalWriteLens>=totalSize: ");
return;
}
leftLen=0;
}
}
Log.d (TAG, "传输已完成: ");
fout.close ();
Log.d (TAG, "totalWriteLens: "+totalWriteLens);
}
socket.close ();
}
} catch (IOException e) {
e.printStackTrace ();
}
}
/**
*
* @param buf 读取大小
* @param writeLen 已经写入到文件中的
* @param leftLen 内存中剩余的字节长度
*/
public static void move( byte buf[] ,int writeLen, int leftLen){
for (int i = 0; i < leftLen; i++) {
if(buf[writeLen+i] != 0){
buf[i] = buf[writeLen+i];
}
}
}
}
传输端
package com.example.socketserivce.activity;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import com.example.socketserivce.R;
import java.io.BufferedInputStream;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
public class SendActivity extends AppCompatActivity {
public static final String TAG="SendActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate (savedInstanceState);
setContentView (R.layout.activity_send);
new Thread (){
@Override
public void run() {
startSocket();
try {
Log.d (TAG, "本机地址: "+InetAddress.getLocalHost ());
} catch (UnknownHostException e) {
e.printStackTrace ();
}
}
}.start ();
}
private void startSocket() {
String path="/data/data/com.example.socketserivce/cache/Image1";
int totalSzie=0;//用来记录已传输文件的总大小
byte buf[]=new byte[8192];
int len;
try {
Socket socket=new Socket ("127.0.0.1",8888);
Log.d (TAG, "成功连接到端口: ");
File file=new File (path);
//将文件夹中的文件添加到 列表中
File[] files=file.listFiles ();
if (file.exists ()){
//socket中收到输出流
DataOutputStream dout=new DataOutputStream (socket.getOutputStream ());
//传入文件的个数
dout.writeInt (files.length);
//传入名字和大小
for (int i=0;i<files.length;i++){
//在输出流中写入名字
dout.writeUTF (files[i].getName ());
dout.flush ();
//在输出流中写入文件大小
dout.writeLong (files[i].length ());
dout.flush ();
totalSzie+=files[i].length ();
}
dout.writeLong (totalSzie);
Log.d (TAG, "传输文件总大小: "+totalSzie);
for (int i=0;i<files.length;i++){
//缓存输入流
BufferedInputStream din=new BufferedInputStream (new FileInputStream (files[i]));
while((len=din.read (buf))!=-1){//-1表示为读取为空,din.read()返回读取的字节数,存储到一个字节数组buf中
dout.write (buf,0,len);//将一个字节数组中,从off开始,到len个字节写入到输出流
}
Log.d (TAG, "第几个文件: "+i);
}
Log.d (TAG, "发送完成。。。。: ");
//关闭流
dout.close ();
}
} catch (IOException e) {
e.printStackTrace ();
}
}
}
解决了!把这里的对负数判定取消,就可以了
已经解决
这种问题自己打log看log,发送数据的长度,接收到数据长度,长度对上了,就比较md5值。实际开发中我们不会直接使用socker传字节数据,而是socket+协议,自己写一套协议。否则你不知道数据段各内容,如果你是间隔发的还好,接收端收完数据就结束了,如果你连续发呢,怎么知道哪里是头,哪里是尾,是什么类型的数据,对吧。通常来说,我们会定义协议,第几个到第几位是数据头,描述后面的内容,什么类型,数据长度,校验值之类的。根据数据头去读取后面的数据,解析出来的数据就是完整的了。