我通过linux端传送图片到服务器端,由于tcp协议具有MTU的规定,所以一张照片会被分成多包传输。
下面是我的c和python代码,python为接收端,c为发送端,后续会进行优化。
C代码(client):
读取图片并传输
#include "tcpmqtt.h"
#include <sys/stat.h>
unsigned long get_file_size(const char *path)
{
unsigned long filesize = -1;
struct stat statbuff;
if(stat(path, &statbuff) < 0){
return filesize;
}else{
filesize = statbuff.st_size;
}
return filesize;
}
int publish_picture(char *ip, int port, char* path)
{
unsigned char image_head[] = {0x8f, 0x8d, 0x00, 0x00, 0x00, 0x00};
char recvline[4096],sendline[4096];
struct sockaddr_in servaddr;
int sockfd, len;
memset(&servaddr,0,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(port);
FILE *fp;
int file_size = 0;
//创建socket
if( (sockfd = socket(AF_INET,SOCK_STREAM,0)) == -1) {
printf(" create socket error: %s (errno :%d)\n",strerror(errno),errno);
return -1;
}
file_size = get_file_size(path);
printf("file size : %d \n", file_size);
image_head[2] = ((file_size & 0xff000000)>>24);
image_head[3] = ((file_size & 0xff0000) >> 16);
image_head[4] = ((file_size & 0xff00) >> 8);
image_head[5] = ((file_size & 0xff));
if((fp = fopen(path, "rb")) == NULL)
{
printf("open picture failed\n");
return -1;
}
if( inet_pton(AF_INET,ip, &servaddr.sin_addr) <=0 ) {
printf("inet_pton error for %s\n", ip);
return -1;
}
//连接
if( connect(sockfd,(struct sockaddr*)&servaddr,sizeof(servaddr)) <0) {
printf(" connect socket error: %s(errno :%d)\n",strerror(errno),errno);
return -1;
}
if ( send(sockfd, image_head, sizeof(image_head), 0) <0) {
printf("send msg error: %s(errno :%d)\n",strerror(errno),errno);
return -1;
}
while(!feof(fp)){
len = fread(sendline, 1, sizeof(sendline), fp);
if(len != write(sockfd, sendline, len)){
printf("write..\n");
break;
}
}
fclose(fp);
close(sockfd);
}
python代码,接收图片并解析:
# -*- coding: utf-8 -*-
"""
Created on Mon Nov 25 10:54:58 2019
@author: admin
"""
from socket import *
def recv_cmd_head(socketid, headsize):
recv_data = socketid.recv(headsize)
recvlen = 0
#print('recv len:', len(recv_data))
if len(recv_data) != headsize:
return 0
if recv_data[0] == 143 and recv_data[1] == 141:
print(recv_data[0], recv_data[1])
recvlen = recv_data[2] * 16777216 + recv_data[3] * 65536 + \
recv_data[4] * 256 + recv_data[5]
return recvlen
def recv_picture(socketid, size, path):
#recv_data = 0
count = 0
#wb以二进制方式写文件,因为我们的tcp接收数据为二进制byte的类型
file = open(path, 'wb')
while True:
recv_data = socketid.recv(size)
print(count, len(recv_data))
if len(recv_data) != 0:
count += len(recv_data)
file.write(recv_data);
else:
file.close()
break
if __name__ == '__main__':
picpath = 'C:/Users/admin/Desktop/pycode/pictest.png'
headsize = 6
tcp_server_socket = socket(AF_INET, SOCK_STREAM)
# 本地信息
address = ('', 7788)
tcp_server_socket.bind(address)
tcp_server_socket.listen(128)
client_socket, clientAddr = tcp_server_socket.accept()
recv_len = recv_cmd_head(client_socket, headsize)
print('应接收到的数据为:', recv_len)
recv_picture(client_socket, recv_len, picpath)
client_socket.close()