长连接(连续传输)的tcp传图在网上的博客和资源寥寥无几,所以写下这篇博客记录一下
一、TCP基础通信程序
这是PC端(C++,JAVA)和Android端的测试程序
TCP通信(PC作为Server,安卓手机作为Client)
二、长连接与连续通信
长连接
长连接就是保持一个心跳信号,过一段时间就连接一次,告诉对面自己还在
连续通信
连续通信是在一个端口上进行持续不断的传输,这个时候相比简单的传输而言,需要保持tcp端口连接
三、程序
PC端(JAVA)程序:
在主程序中加入javanew SocketTest2();
即可
package com.company;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.nio.channels.FileChannel;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
public class SocketTest2 {
private ScheduledThreadPoolExecutor mScheduledThreadPoolExecutor = null;
private Runnable mRunnable = null;
private ScheduledFuture<?> mScheduledFuture = null;
private Socket mSocket = null;
int i=0;
private Logger mLogger = Logger.getLogger(SocketTest2.class.getName());
private void session() {
FileInputStream dis = null;
OutputStream dos = null;
try {
while (true) {
dis =new FileInputStream("C:\\Users\\S\\Desktop\\Gray_coat\\"+i+".jpg");
System.out.println(dis.available());
FileChannel fc = dis.getChannel();
mLogger.info(String.valueOf(fc.size()));
dos = mSocket.getOutputStream();
mLogger.info("准备");
String data = "PC时间:" + System.currentTimeMillis();
byte[] buf = new byte[1024];
int len =0;
while((len=dis.read(buf))!=-1) {
dos.write(buf, 0, len);
}
//dos.flush();
mLogger.info("传完");
i++;
Thread.sleep(500);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
mSocket.close();
} catch (Exception e) {
e.printStackTrace();
}
mSocket = null;
}
}
public SocketTest2() {
mScheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(1);
mRunnable = new Runnable() {
@Override
public void run() {
if (mSocket == null || !mSocket.isConnected()) {
mLogger.info("尝试建立连接...");
try {
mSocket = new Socket("localhost", 7778);
mLogger.info("建立新连接:" + mSocket.toString());
CompletableFuture.runAsync(new Runnable() {
@Override
public void run() {
session();
}
});
} catch (Exception e) {
mLogger.info("连接异常");
}
} else {
mLogger.info("连接心跳检测:当前已经建立连接,无需重连");
}
}
};
// 每隔3秒周期性的执行心跳检测动作。
mScheduledFuture = mScheduledThreadPoolExecutor.scheduleAtFixedRate(mRunnable, 0, 1, TimeUnit.SECONDS);
}
}
Android端程序:
package com.example.tongxin;
import androidx.appcompat.app.AppCompatActivity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.ImageView;
import android.widget.Toast;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import android.widget.TextView;
import android.os.Bundle;
import android.util.Log;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class MainActivity extends AppCompatActivity {
private String TAG = "Android端";
static boolean Flag = false;
ImageView image = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
image = (ImageView) findViewById(R.id.image);
new ServerThread().start();
}
private class ServerThread extends Thread {
@Override
public void run() {
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(7777);
while (true) {
Socket socket = serverSocket.accept();
Log.d(TAG, "接受连接");
try {
System.out.println("开始接受图片时间" + System.currentTimeMillis());
InputStream bis = socket.getInputStream();
System.out.println(bis.available());
System.out.println("图片解码前时间" + System.currentTimeMillis());
Bitmap bitmap = BitmapFactory.decodeStream(bis);
System.out.println("关闭流前时间" + System.currentTimeMillis());
bis.close();
System.out.println("输出图片前时间" + System.currentTimeMillis());
runOnUiThread(new Runnable() {
@Override
public void run() {
//更新UI
image.setImageBitmap(bitmap);
System.out.println("输出图片后时间" + System.currentTimeMillis());
}
});
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
//socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (serverSocket != null) {
try {
//serverSocket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
}
再在layout中加入一个imageview:
<ImageView
android:id="@+id/image"
android:layout_width="320dp"
android:layout_height="520dp"
tools:ignore="MissingConstraints"/>
注意:在java中可以直接用mSocket.getOutputStream().write()发送数据,用socket.getInputStream()接收数据,这是一一对应的,如果使用c++平台的tcp通信,就需要添加代码进行适配。