环境:
Server: Ubuntu 14.04 LTS + OpenCV2.4.10
Client:: Ubuntu 14.04 LTS + OpenCV2.4.10
我采用的仍是TCP协议的通信,linux上的实现和Windows大同小异。
TCP协议通信的一般步骤我再重新说一下:
客户端:
1、创建一个socket,用函数socket();
2、设置socket属性,用函数setsockopt();* 可选
3、绑定IP地址、端口等信息到socket上,用函数bind();* 可选
4、设置要连接的对方的IP地址和端口等属性;
5、连接服务器,用函数connect();
6、收发数据,用函数send()和recv(),或者read()和write();
7、关闭网络连接;
服务器端:
1、创建一个socket,用函数socket();
2、设置socket属性,用函数setsockopt(); * 可选
3、绑定IP地址、端口等信息到socket上,用函数bind();
4、开启监听,用函数listen();
5、接收客户端上来的连接,用函数accept();
6、收发数据,用函数send()和recv(),或者read()和write();
7、关闭网络连接;
8、关闭监听;
我把图像的发送和接收分别封装在了两个类中:
采集与发送:
SocketMatTransmissionClient.h
/*M///
//
// 基于OpenCV和Socket的图像传输(发送)
//M*/
#ifndef __SOCKETMATTRANSMISSIONCLIENT_H__
#define __SOCKETMATTRANSMISSIONCLIENT_H__
#include "opencv2/opencv.hpp"
#include
#include
#include
#include
#include
#include
#include
#include
#include
usingnamespacecv;
//待传输图像默认大小为 640*480,可修改
#define IMG_WIDTH 640 // 需传输图像的宽
#define IMG_HEIGHT 480 // 需传输图像的高
#define PACKAGE_NUM 2
//默认格式为CV_8UC3
#define BUFFER_SIZE IMG_WIDTH*IMG_HEIGHT*3/PACKAGE_NUM
structsentbuf
{
charbuf[BUFFER_SIZE];
intflag;
};
classSocketMatTransmissionClient
{
public:
SocketMatTransmissionClient(void);
~SocketMatTransmissionClient(void);
private:
intsockClient;
structsentbuf data;
public:
// 打开socket连接
// params : IP 服务器的ip地址
// PORT 传输端口
// return : -1 连接失败
// 1 连接成功
intsocketConnect(constchar* IP,intPORT);
// 传输图像
// params : image 待传输图像
// return : -1 传输失败
// 1 传输成功
inttransmit(cv::Mat image);
// 断开socket连接
voidsocketDisconnect(void);
};
#endif
SocketMatTransmissionClient.cpp
/*M///
//
// 基于OpenCV和Socket的图像传输(发送)
//M*/
#include "SocketMatTransmissionClient.h"
SocketMatTransmissionClient::SocketMatTransmissionClient(void)
{
}
SocketMatTransmissionClient::~SocketMatTransmissionClient(void)
{
}
intSocketMatTransmissionClient::socketConnect(constchar* IP,intPORT)
{
structsockaddr_in servaddr;
if((sockClient = socket(AF_INET, SOCK_STREAM, 0))
{
printf("create socket error: %s(errno: %d)\n", strerror(errno), errno);
return-1;
}
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(PORT);
if(inet_pton(AF_INET, IP, &servaddr.sin_addr) <= 0)
{
printf("inet_pton error for %s\n", IP);
return-1;
}
if(connect(sockClient, (structsockaddr*)&servaddr,sizeof(servaddr))
{
printf("connect error: %s(errno: %d)\n", strerror(errno), errno);
return-1;
}
else
{
printf("connect successful!\n");
}
}
voidSocketMatTransmissionClient::socketDisconnect(void)
{
close(sockClient);
}
intSocketMatTransmissionClient::transmit(cv::Mat image)
{
if(image.empty())
{
printf("empty image\n\n");
return-1;
}
if(image.cols != IMG_WIDTH || image.rows != IMG_HEIGHT || image.type() != CV_8UC3)
{
printf("the image must satisfy : cols == IMG_WIDTH(%d) rows == IMG_HEIGHT(%d) type == CV_8UC3\n\n", IMG_WIDTH, IMG_HEIGHT);
return-1;
}
for(intk = 0; k
{
intnum1 = IMG_HEIGHT / PACKAGE_NUM * k;
for(inti = 0; i
{
intnum2 = i * IMG_WIDTH * 3;
uchar* ucdata = image.ptr(i + num1);
for(intj = 0; j
{
data.buf[num2 + j] = ucdata[j];
}
}
if(k == PACKAGE_NUM - 1)
data.flag = 2;
else
data.flag = 1;
if(send(sockClient, (char*)(&data),sizeof(data), 0)
{
printf("send image error: %s(errno: %d)\n", strerror(errno), errno);
return-1;
}
}
}
接收与显示:
SocketMatTransmissionServer.h
/*M///
//
// 基于OpenCV和Socket的图像传输(接收)
//M*/
#ifndef __SOCKETMATTRANSMISSIONSEVER_H__
#define __SOCKETMATTRANSMISSIONSEVER_H__
#include "opencv2/opencv.hpp"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
usingnamespacecv;
#define PACKAGE_NUM 2
#define IMG_WIDTH 640
#define IMG_HEIGHT 480
#define BLOCKSIZE IMG_WIDTH*IMG_HEIGHT*3/PACKAGE_NUM
structrecvBuf
{
charbuf[BLOCKSIZE];
intflag;
};
classSocketMatTransmissionServer
{
public:
SocketMatTransmissionServer(void);
~SocketMatTransmissionServer(void);
intsockConn;
private:
structrecvBuf data;
intneedRecv;
intcount;
public:
// 打开socket连接
// params : PORT 传输端口
// return : -1 连接失败
// 1 连接成功
intsocketConnect(intPORT);
// 传输图像
// params : image 待接收图像
// image 待接收图像
// return : -1 接收失败
// 1 接收成功
intreceive(cv::Mat& image);
// 断开socket连接
voidsocketDisconnect(void);
};
#endif
SocketMatTransmissionServer.cpp
/*M///
//
// 基于OpenCV和Socket的图像传输(接收)
//
//M*/
#include "SocketMatTransmissionServer.h"
SocketMatTransmissionServer::SocketMatTransmissionServer(void)
{
}
SocketMatTransmissionServer::~SocketMatTransmissionServer(void)
{
}
intSocketMatTransmissionServer::socketConnect(intPORT)
{
intserver_sockfd = socket(AF_INET,SOCK_STREAM, 0);
structsockaddr_in server_sockaddr;
server_sockaddr.sin_family = AF_INET;
server_sockaddr.sin_port = htons(PORT);
server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(server_sockfd,(structsockaddr *)&server_sockaddr,sizeof(server_sockaddr))==-1)
{
perror("bind");
return-1;
}
if(listen(server_sockfd,5) == -1)
{
perror("listen");
return-1;
}
structsockaddr_in client_addr;
socklen_t length = sizeof(client_addr);
sockConn = accept(server_sockfd, (structsockaddr*)&client_addr, &length);
if(sockConn<0)
{
perror("connect");
return-1;
}
else
{
printf("connect successful!\n");
return1;
}
close(server_sockfd);
}
voidSocketMatTransmissionServer::socketDisconnect(void)
{
close(sockConn);
}
intSocketMatTransmissionServer::receive(cv::Mat& image)
{
intreturnflag = 0;
cv::Mat img(IMG_HEIGHT, IMG_WIDTH, CV_8UC3, cv::Scalar(0));
needRecv = sizeof(recvBuf);
count = 0;
memset(&data,0,sizeof(data));
for(inti = 0; i
{
intpos = 0;
intlen0 = 0;
while(pos
{
len0 = recv(sockConn, (char*)(&data) + pos, needRecv - pos, 0);
if(len0
{
printf("Server Recieve Data Failed!\n");
break;
}
pos += len0;
}
count = count + data.flag;
intnum1 = IMG_HEIGHT / PACKAGE_NUM * i;
for(intj = 0; j
{
intnum2 = j * IMG_WIDTH * 3;
uchar* ucdata = img.ptr(j + num1);
for(intk = 0; k
{
ucdata[k] = data.buf[num2 + k];
}
}
if(data.flag == 2)
{
if(count == PACKAGE_NUM + 1)
{
image = img;
returnflag = 1;
count = 0;
}
else
{
count = 0;
i = 0;
}
}
}
if(returnflag == 1)
return1;
else
return-1;
}
示例代码:
图像的采集与发送:
SocketClientMat.cpp
#include "SocketMatTransmissionClient.h"
intmain()
{
SocketMatTransmissionClient socketMat;
if(socketMat.socketConnect("127.0.0.1", 6666)
{
return0;
}
cv::VideoCapture capture(0);
cv::Mat image;
while(1)
{
if(!capture.isOpened())
return0;
capture >> image;
if(image.empty())
return0;
socketMat.transmit(image);
}
socketMat.socketDisconnect();
return0;
}
接收与显示:
SocketServerMat.cpp
#include "SocketMatTransmissionServer.h"
intmain()
{
SocketMatTransmissionServer socketMat;
if(socketMat.socketConnect(6666)
{
return0;
}
cv::Mat image;
while(1)
{
if(socketMat.receive(image) > 0)
{
cv::imshow("",image);
cv::waitKey(30);
}
}
socketMat.socketDisconnect();
return0;
}