基于C++tcp传输Base64编解码升级版

 · 2023-12-29 · 次阅读


服务端程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#include <winsock2.h>
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <algorithm>

#pragma comment(lib, "ws2_32.lib")

static const std::string base64_chars =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";

// 检查字符是否属于Base64编码字符集
static inline bool is_base64(unsigned char c) {
return (isalnum(c) || (c == '+') || (c == '/'));
}

// 清理Base64字符串,移除非Base64字符
std::string cleanBase64String(const std::string& input) {
std::string output;
output.reserve(input.size());

std::copy_if(input.begin(), input.end(), std::back_inserter(output), is_base64);

return output;
}

// Base64解码函数
std::string base64_decode(std::string const& encoded_string) {
int in_len = encoded_string.size();
int i = 0;
int j = 0;
int in_ = 0;
unsigned char char_array_4[4], char_array_3[3];
std::string ret;

while (in_len-- && (encoded_string[in_] != '=') && is_base64(encoded_string[in_])) {
char_array_4[i++] = encoded_string[in_]; in_++;
if (i == 4) {
for (i = 0; i < 4; i++)
char_array_4[i] = base64_chars.find(char_array_4[i]);

char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];

for (i = 0; (i < 3); i++)
ret += char_array_3[i];
i = 0;
}
}

if (i) {
for (j = i; j < 4; j++)
char_array_4[j] = 0;

for (j = 0; j < 4; j++)
char_array_4[j] = base64_chars.find(char_array_4[j]);

char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];

for (j = 0; (j < i - 1); j++) ret += char_array_3[j];
}

return ret;
}

int main() {
WSADATA wsaData;
SOCKET serverSocket, clientSocket;
struct sockaddr_in server, client;
char buffer[1024] = {0};
int clientSize = sizeof(client);

if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) {
std::cerr << "Winsock initialization failed. Error code: " << WSAGetLastError() << std::endl;
return 1;
}

if ((serverSocket = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
std::cerr << "Socket creation failed. Error code: " << WSAGetLastError() << std::endl;
WSACleanup();
return 1;
}

server.sin_family = AF_INET;
server.sin_addr.s_addr = inet_addr("192.168.50.218"); // Specific IP address
server.sin_port = htons(8888);

if (bind(serverSocket, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR) {
std::cerr << "Bind failed. Error code: " << WSAGetLastError() << std::endl;
closesocket(serverSocket);
WSACleanup();
return 1;
}

listen(serverSocket, 3);
std::cout << "Waiting for incoming connections..." << std::endl;

while (true) { // Main loop to accept new connections
clientSocket = accept(serverSocket, (struct sockaddr *)&client, &clientSize);
if (clientSocket == INVALID_SOCKET) {
std::cerr << "Accepting connection failed. Error code: " << WSAGetLastError() << std::endl;
continue;
}

std::cout << "Connection established!" << std::endl;
std::stringstream ss;

while (true) { // Loop for handling multiple data transfers within the same connection
memset(buffer, 0, 1024);
int bytesReceived = recv(clientSocket, buffer, 1024, 0);
if (bytesReceived == SOCKET_ERROR || bytesReceived == 0) {
std::cerr << "Client disconnected" << std::endl;
break;
}

ss << buffer;
if (ss.str().find("END") != std::string::npos) {
std::string encoded_str = ss.str();
size_t end_pos = encoded_str.find("END");
encoded_str = encoded_str.substr(0, end_pos);

std::string clean_encoded_str = cleanBase64String(encoded_str);
std::string decoded_data = base64_decode(clean_encoded_str);

std::ofstream output_file("output.jpg", std::ios::binary);
if (output_file.is_open()) {
output_file.write(decoded_data.c_str(), decoded_data.size());
output_file.close();
std::cout << "Decoded image written to output.jpg" << std::endl;

send(clientSocket, "START", 5, 0);
ss.clear();
ss.str("");
} else {
std::cerr << "Failed to open output file." << std::endl;
}
}
}

closesocket(clientSocket); // Close the client socket
}

closesocket(serverSocket);
WSACleanup();
return 0;
}

客户端程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#include <iostream>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <cstring>
#include <fstream>
#include <vector>
#include <string>
#include <sstream>

static const std::string base64_chars =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";

std::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len) {
std::string ret;
int i = 0;
int j = 0;
unsigned char char_array_3[3];
unsigned char char_array_4[4];

while (in_len--) {
char_array_3[i++] = *(bytes_to_encode++);
if (i == 3) {
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
char_array_4[3] = char_array_3[2] & 0x3f;

for(i = 0; (i <4) ; i++)
ret += base64_chars[char_array_4[i]];
i = 0;
}
}

if (i)
{
for(j = i; j < 3; j++)
char_array_3[j] = '\0';

char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
char_array_4[3] = char_array_3[2] & 0x3f;

for (j = 0; (j < i + 1); j++)
ret += base64_chars[char_array_4[j]];

while((i++ < 3))
ret += '=';
}

return ret;
}

int main() {
int sock;
struct sockaddr_in server;
bool transferCompleted = false;

while (!transferCompleted) {
// 创建套接字
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == -1) {
std::cerr << "Could not create socket" << std::endl;
return 1;
}

server.sin_addr.s_addr = inet_addr("192.168.50.218");
server.sin_family = AF_INET;
server.sin_port = htons(8888);

// 连接到服务器
if (connect(sock, (struct sockaddr *)&server, sizeof(server)) < 0) {
std::cerr << "Connect failed. Error" << std::endl;
close(sock);
return 1;
}

std::cout << "Connected to server" << std::endl;

// 读取和发送图像文件
std::ifstream file("./image0.jpg", std::ios::binary);
if (!file.is_open()) {
std::cerr << "Failed to open file." << std::endl;
close(sock);
return 1;
}

std::vector<unsigned char> buffer(std::istreambuf_iterator<char>(file), {});
std::string encoded = base64_encode(&buffer[0], buffer.size());

send(sock, encoded.c_str(), encoded.length(), 0);
send(sock, "END", 3, 0);

// 接收来自服务器的响应
char response[1024] = {0};
std::stringstream ss;
int bytesReceived = recv(sock, response, 1024, 0);
if (bytesReceived <= 0) {
std::cerr << "Receive failed or connection closed" << std::endl;
close(sock);
break;
}

ss << response;
if (ss.str().find("START") == std::string::npos) {
transferCompleted = true;
}

close(sock); // 关闭当前套接字
}

return 0;
}