客户端发送图像到服务端,服务端对图像进行处理,在将处理后的图像发送到客户端,并且服务端持续监听客户端。
客户端
#include <iostream>
#include <fstream>
#include <vector>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <opencv2/opencv.hpp>
#define PORT 8080
#define BUFFER_SIZE 1024
#define IMAGE_PATH "image.jpg"
#define RESULT_IMAGE_PATH "result.jpg"
int main() {
int sock = 0, valread;
struct sockaddr_in serv_addr;
char buffer[BUFFER_SIZE] = {0};
// 创建套接字
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
std::cerr << "Socket creation error" << std::endl;
return -1;
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
// 将IPv4地址从文本转换为二进制形式
if(inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr)<=0) {
std::cerr << "Invalid address/ Address not supported" << std::endl;
return -1;
}
// 连接到服务器
if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
std::cerr << "Connection Failed" << std::endl;
return -1;
}
// 读取图像文件
std::ifstream file(IMAGE_PATH, std::ios::binary);
if (!file) {
std::cerr << "Failed to open file: " << IMAGE_PATH << std::endl;
return -1;
}
std::vector<unsigned char> imageData((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
// 发送图像数据到服务器
send(sock, imageData.data(), imageData.size(), 0);
std::cout << "Image sent to server" << std::endl;
// 关闭发送方向的连接
shutdown(sock, SHUT_WR);
// 接收服务器的处理结果
std::vector<unsigned char> resultData;
while (true) {
valread = read(sock, buffer, BUFFER_SIZE);
if (valread <= 0) {
break;
}
resultData.insert(resultData.end(), buffer, buffer + valread);
}
std::ofstream resultFile(RESULT_IMAGE_PATH, std::ios::binary);
resultFile.write(reinterpret_cast<const char*>(resultData.data()), resultData.size());
resultFile.close();
std::cout << "Result image received and saved as: " << RESULT_IMAGE_PATH << std::endl;
return 0;
}
服务端
#include <iostream>
#include <vector>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <opencv2/opencv.hpp>
#define PORT 8080
#define BUFFER_SIZE 1024
void processImage(const std::vector<unsigned char>& imageData, std::vector<unsigned char>& resultData) {
cv::Mat image = cv::imdecode(imageData, cv::IMREAD_COLOR);
// 在这里进行图像处理,这里只是一个示例,将图像水平翻转
cv::flip(image, image, 1);
// 将处理后的图像编码为JPEG格式
std::vector<int> params;
params.push_back(cv::IMWRITE_JPEG_QUALITY);
params.push_back(90);
cv::imencode(".jpg", image, resultData, params);
sleep(3);
}
int main() {
int server_fd, new_socket, valread;
struct sockaddr_in address;
int opt = 1;
int addrlen = sizeof(address);
char buffer[BUFFER_SIZE] = {0};
// 创建套接字
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
perror("socket failed");
exit(EXIT_FAILURE);
}
// 设置套接字选项,允许地址重用
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))) {
perror("setsockopt");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(PORT);
// 绑定套接字到指定端口
if (bind(server_fd, (struct sockaddr *)&address, sizeof(address))<0) {
perror("bind failed");
exit(EXIT_FAILURE);
}
// 监听连接
if (listen(server_fd, 3) < 0) {
perror("listen");
exit(EXIT_FAILURE);
}
while(1)
{
// 接受连接
if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen))<0) {
perror("accept");
exit(EXIT_FAILURE);
}
// 从客户端读取图像数据
std::vector<unsigned char> imageData;
while (true) {
valread = read(new_socket, buffer, BUFFER_SIZE);
if (valread <= 0) {
break;
}
imageData.insert(imageData.end(), buffer, buffer + valread);
}
std::cout << "Received " << imageData.size() << " bytes of image data" << std::endl;
// 处理图像数据
std::vector<unsigned char> resultData;
processImage(imageData, resultData);
// 向客户端发送处理后的结果
send(new_socket, resultData.data(), resultData.size(), 0);
std::cout << "Processed image sent to client" << std::endl;
close(new_socket);
}
return 0;
}