由于在实验室做项目的需要,参考了博客上的各种代码,然后自己写写改改搞了十几天,今天终于有点模样了,然后分享出来也算是笔记又可以给后面的兄弟分享经验。(可能一时间不会太完善我会一直修改完善,后面工程会分享到我的GitHub,毕竟现在的博客会员太贵)
还是先上代码吧。不过我做的是android作为服务器端(接收显示图像),PC端作为客户端(发送图像)。
1、android服务器端(开发平台是androidstudio):
①权限设置。socket通信是TCP/IP方式,相当于局域网,必须获取网络权限
<uses-permission android:name="android.permission.INTERNET" />
②部分关键代码。关键代码就是一个线程,因为通信的连接是阻塞机制(开始我也不懂,后来一想也挺简单的,你android端是服务器端,就像你想从别人那儿通过电话得到你中了大奖的消息,此刻别人还没打来电话你就只能坐着干等,一直等就形成了阻塞,等到别人打来电话,电话响了你接通电话就建立了通信。如果主线程也来这样等的话就是让大老板等手下浪费资源,就派一个小弟去等就行了于是建立一个子线程去等),子线程程序(绿色为关键代码,而且服务器端代码和客户端代码颜色对应):
public class SocketServerPictureThread extends Thread {
public String Length; //用来放客户端发过来图像的长度
private Socket socket;
private int offset=0;
private BufferedOutputStream output; //输出流
private BufferedInputStream input; //输入流
@Override
public void run() {
try {
ServerSocket serverSocket = new ServerSocket(9000); //服务器端端口,数据就是在这个端口上
while (true) {
socket = serverSocket.accept(); //他就是阻塞,没电话来就一直等,下面都执行不了
//电话一来就建立连接,开始执行下面代码
output=new BufferedOutputStream(socket.getOutputStream());
input=new BufferedInputStream(socket.getInputStream());
Length=readMsgFromSocket(input); //对面发来了图像大小,我好准备空间
send_msg.post(new Runnable() {
@Override
public void run() {
send_msg.setText(Length); //这是为了看到图像大小,线程中必须这样才能显示到UI界面
}
});
SendMsg("123"); //随便发送的,让对面知道我收到了长度
byte[] bitmapBuff=new byte[Integer.valueOf(Length)]; //分配放图片的空间
while (offset<Integer.valueOf(Length))
{
int len=input.read(bitmapBuff,offset,Integer.valueOf(Length)-offset);//读取图像数据放空间里
offset+=len;
}
Length="";
final Bitmap bitmap=BitmapFactory.decodeByteArray(bitmapBuff,0,offset); //解压图像文件
image.post(new Runnable() {
@Override
public void run() {
image.setImageBitmap(bitmap); //将图片在UI上显示出来
}
});
SendMsg("12"); //告诉客户端这边图像已经接收完,我们可以挂了
socket.close(); //我先挂了电话先
offset=0; //这点比较坑,参考的博客都没有写,让我调了几天,为什么第一张传了第二张就出问题了呢,原因是offset没复位为 0 ,第二个开始还是前面的值,一张完了就开始从新建立连接接收下一张图片了
}
} catch (IOException e) {
e.printStackTrace();
}
}
public String readMsgFromSocket(InputStream in) { //读取客户端发过来的文本数据
String msg = "";
byte[] tempbuffer = new byte[1024];
try {
int numReadedBytes = in.read(tempbuffer, 0, tempbuffer.length);
msg = new String(tempbuffer, 0, numReadedBytes, "utf-8");
} catch (Exception e) {
e.printStackTrace();
}
return msg;
}
public void SendMsg(String msg) { //发送文本数据给客户端
String msg_1 = msg;
try {
output.write(msg_1.getBytes("UTF-8"));
output.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
2、PC客户端(pycharm平台):
①客户端就简单了,前面不是在等消息嘛,我这边只要给他打电话就行,他那边可能等得有点久了,直接全部代码:
# -*- coding: utf-8 -*-
import _thread
import socket
import os
def server_picture_socket():
picture_number = 1 //第几张图像
current_picture_dir = os.path.dirname(os.path.abspath(__file__)) //读取图像的文件地址
while True:
client_address = ('127.0.0.1', 5000)
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) //这个就是“拨打电话”了
client_socket.connect(client_address)
print("准备发送")
if picture_number>3://我一共连续传了3张图,如果多来个几百张就是视频了
picture_number=1
server_picture_path = os.path.join(current_picture_dir, str(picture_number) + ".jpg")
print(server_picture_path)
while os.path.exists(server_picture_path):
server_picture_open = open(server_picture_path, 'rb')
file_size = os.stat(server_picture_path).st_size
x = str(file_size)
client_socket.send(x.encode("UTF-8")) //接通了电话,告诉服务器端你可能要接收 // 的图像大小,让他可以分配放图像空间的大小了,为我准备好包间
eee= client_socket.recv(1024).decode() //晓得服务器端接收到了长度
length = 0
while length != file_size:
pictrue_data = server_picture_open.read(1024)
client_socket.sendall(pictrue_data) //发送图像数据给服务器端
length += len(pictrue_data)
server_picture_open.close()
picture_number += 1
re = client_socket.recv(1024).decode() //对面发过来消息他已经接收完图像
client_socket.close() //接收完了呀,你挂了我也挂吧,还有消息就再给你打电话了
break
print("发送完毕")
if __name__ == '__main__':
server_picture_socket()
3、通过USB是android的一个adb,所以要配置端口和adb环境的添加:
环境添加就先在androidstudio的setting中找到SDK文件地址,里面有个adb文件,再在环境变量中添加就行:可百度;
cmd键入 adb 出现该图就添加好了,然后就是端口的匹配:
接着键入 adb forward tcp:5000 tcp:9000 (端口程序中有)
啊,写了接近2个小时,毕竟我的水平有限,不然的话我两天就搞定这个垃圾程序了
后面传到github上,目前觉得有用的可以直接联系我发工程