添加一个TCP示例和一个Curl下载文件示例
This commit is contained in:
parent
4ca30574a9
commit
54310e4b29
86
cpp/algorithm/类似Base64算法.cpp
Normal file
86
cpp/algorithm/类似Base64算法.cpp
Normal file
@ -0,0 +1,86 @@
|
||||
#include <iostream>
|
||||
#include <bitset>
|
||||
#include <cstring>
|
||||
|
||||
// 问题:将一个二进制流转换成可阅读的字符串,字符串为:大写字母加数字,去除0和O,I和1相近字符。
|
||||
|
||||
const int g_bitNum = 5;
|
||||
const char* g_Coder = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
|
||||
|
||||
int Encode(const char* pData, int nLen, char* res)
|
||||
{
|
||||
int totalLen = nLen * 8;
|
||||
int resLen = totalLen / g_bitNum;
|
||||
if (totalLen % g_bitNum != 0) ++resLen;
|
||||
if (res == nullptr) {
|
||||
return resLen;
|
||||
}
|
||||
for (int i = 0; i < resLen; ++i) {
|
||||
unsigned char nIndex = 0;
|
||||
int index = i * g_bitNum;
|
||||
for (int j = 0; j < g_bitNum && index + j < totalLen; ++j) {
|
||||
|
||||
// bitValue 这一行只管取出下一位的值,放在哪里不管。
|
||||
// index 是连续的(相当于大组里面内增,换个大组继续内增)
|
||||
// index / 8 或者 index % 8 就是锁定第几组char的第几个,移动到最低位取出。
|
||||
unsigned char bitValue = ((pData[index / 8] >> (7 - index % 8)) & 1);
|
||||
|
||||
// value 这一行只管把值放到对应的位置,与上面不要联系。
|
||||
// 这里对 value 高位到低位的放
|
||||
nIndex |= (bitValue << (g_bitNum - 1 - j));
|
||||
|
||||
// 关键点:value 和 bitValue 各管各的。
|
||||
++index;
|
||||
}
|
||||
res[i] = g_Coder[nIndex];
|
||||
}
|
||||
res[resLen] = '\0';
|
||||
return resLen;
|
||||
}
|
||||
|
||||
int Decode(const char* pData, unsigned char* res)
|
||||
{
|
||||
int len = static_cast<int>(std::strlen(pData));
|
||||
int codeBitCount = len * g_bitNum;
|
||||
int resCnt = codeBitCount / 8;
|
||||
if (res == nullptr) {
|
||||
return resCnt;
|
||||
}
|
||||
std::memset(res, 0, resCnt * sizeof(char));
|
||||
for (int i = 0; i < len; ++i) {
|
||||
const char key = pData[i];
|
||||
int nIndex = static_cast<int>(std::strchr(g_Coder, key) - g_Coder);
|
||||
for (int j = 0; j < g_bitNum && i * g_bitNum + j < codeBitCount; ++j) {
|
||||
// bitValue 这一行,只管取出每一位
|
||||
int bitValue = ((nIndex >> (g_bitNum - 1 - j)) & 1);
|
||||
// nOffset 是原始数据位索引
|
||||
int nOffset = i * g_bitNum + j;
|
||||
res[nOffset / 8] |= (bitValue << (7 - nOffset % 8));
|
||||
}
|
||||
}
|
||||
return resCnt;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int data[] = {12345, 45678};
|
||||
std::cout << "Original Data Len: " << sizeof(data) << std::endl;
|
||||
char* szEncode = nullptr;
|
||||
int size = Encode((const char*)data, sizeof(data), szEncode);
|
||||
std::printf("Encode Data Len: %d\n", size);
|
||||
szEncode = new char[size + 1];
|
||||
Encode((const char*)data, sizeof(data), szEncode);
|
||||
std::printf("Encode Data: %s\n", szEncode);
|
||||
|
||||
unsigned char * szDecode = nullptr;
|
||||
int osize = Decode((const char *)szEncode, szDecode);
|
||||
std::printf("Decode Data Len: %d\n", osize);
|
||||
szDecode = new unsigned char [osize + 1];
|
||||
Decode((const char*)szEncode, szDecode);
|
||||
|
||||
int* pInt = (int *)szDecode;
|
||||
std::printf("Int[0]:%d, Int[1]:%d\n", pInt[0], pInt[1]);
|
||||
delete[] szDecode;
|
||||
delete[] szEncode;
|
||||
return 0;
|
||||
}
|
6
cpp/demo/net/CMakeLists.txt
Normal file
6
cpp/demo/net/CMakeLists.txt
Normal file
@ -0,0 +1,6 @@
|
||||
cmake_minimum_required (VERSION 3.8)
|
||||
|
||||
project (cppNetTool)
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
add_executable(cppNetTool main.cpp multi_thread_down.cpp)
|
||||
target_link_libraries(cppNetTool curl)
|
9
cpp/demo/net/main.cpp
Normal file
9
cpp/demo/net/main.cpp
Normal file
@ -0,0 +1,9 @@
|
||||
#include <iostream>
|
||||
#include "multi_thread_down.h"
|
||||
|
||||
int main(int argc, const char* argv[])
|
||||
{
|
||||
CThreadDownload downloader;
|
||||
downloader.download(argv[1], argv[2]);
|
||||
return 0;
|
||||
}
|
93
cpp/demo/net/multi_thread_down.cpp
Normal file
93
cpp/demo/net/multi_thread_down.cpp
Normal file
@ -0,0 +1,93 @@
|
||||
#include "multi_thread_down.h"
|
||||
|
||||
void CTimer::start()
|
||||
{
|
||||
m_start = std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
|
||||
size_t CTimer::getTime()
|
||||
{
|
||||
m_end = std::chrono::high_resolution_clock::now();
|
||||
std::chrono::milliseconds duration = std::chrono::duration_cast<std::chrono::milliseconds>(m_end - m_start);
|
||||
size_t cnt = duration.count();
|
||||
return cnt;
|
||||
}
|
||||
|
||||
CThreadDownload::CThreadDownload()
|
||||
= default;
|
||||
|
||||
CThreadDownload::~CThreadDownload()
|
||||
= default;
|
||||
|
||||
double CThreadDownload::getFileLength(const char* url)
|
||||
{
|
||||
double len = 0;
|
||||
CURL* curl = curl_easy_init();
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url);
|
||||
curl_easy_setopt(curl, CURLOPT_HEADER, 1);
|
||||
curl_easy_setopt(curl, CURLOPT_NOBODY, 1);
|
||||
if (curl_easy_perform(curl) == CURLE_OK) {
|
||||
curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &len);
|
||||
}
|
||||
else {
|
||||
len = -1;
|
||||
}
|
||||
curl_easy_cleanup(curl);
|
||||
return len;
|
||||
}
|
||||
|
||||
int CThreadDownload::download(const char* url, const char* filename) {
|
||||
|
||||
double fileLen = getFileLength(url);
|
||||
if (fileLen < 0) {
|
||||
std::printf("Failed to obtain the file size!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::ofstream stream(filename, std::ios::binary | std::ios::trunc);
|
||||
if (!stream.is_open()) {
|
||||
std::printf("Open File Failed: %s", filename);
|
||||
return -1;
|
||||
}
|
||||
m_fstream = std::move(stream);
|
||||
|
||||
|
||||
std::printf("File Len: %lf\n", fileLen);
|
||||
|
||||
// try
|
||||
// {
|
||||
// m_fstream.seekp(fileLen - 1);
|
||||
// }
|
||||
// catch(const std::exception& e)
|
||||
// {
|
||||
// std::cerr << e.what() << '\n';
|
||||
// m_fstream.close();
|
||||
// return -1;
|
||||
// }
|
||||
|
||||
CURL* curl = curl_easy_init();
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeFunCall);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, this);
|
||||
|
||||
// 建立TCP连接,发送http请求,等待数据返回
|
||||
CURLcode res = curl_easy_perform(curl);
|
||||
|
||||
if (res != CURLE_OK) {
|
||||
std::printf("res: %d\n", res);
|
||||
}
|
||||
|
||||
curl_easy_cleanup(curl);
|
||||
m_fstream.close();
|
||||
std::cout << "Done." << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t CThreadDownload::writeFunCall(void* ptr, size_t size, size_t mmb, void* userdata)
|
||||
{
|
||||
size_t nSize = size * mmb;
|
||||
CThreadDownload* pDown = (CThreadDownload*)userdata;
|
||||
pDown->m_fstream.write((const char*)ptr, nSize);
|
||||
std::printf("writeFunCall: %ld\n", nSize);
|
||||
return nSize;
|
||||
}
|
38
cpp/demo/net/multi_thread_down.h
Normal file
38
cpp/demo/net/multi_thread_down.h
Normal file
@ -0,0 +1,38 @@
|
||||
#ifndef MULTI_DOWNLOAD_H
|
||||
#define MULTI_DOWNLOAD_H
|
||||
|
||||
#include <curl/curl.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <chrono>
|
||||
|
||||
class CTimer
|
||||
{
|
||||
using time_point_t = std::chrono::high_resolution_clock::time_point;
|
||||
public:
|
||||
CTimer() = default;
|
||||
~CTimer() = default;
|
||||
public:
|
||||
void start();
|
||||
// 秒种
|
||||
size_t getTime();
|
||||
private:
|
||||
time_point_t m_start;
|
||||
time_point_t m_end;
|
||||
};
|
||||
|
||||
class CThreadDownload
|
||||
{
|
||||
public:
|
||||
CThreadDownload();
|
||||
~CThreadDownload();
|
||||
public:
|
||||
double getFileLength(const char* url);
|
||||
int download(const char* url, const char* filename);
|
||||
static size_t writeFunCall(void* ptr, size_t size, size_t mmb, void* userdata);
|
||||
|
||||
private:
|
||||
std::ofstream m_fstream;
|
||||
};
|
||||
|
||||
#endif
|
31
cpp/demo/tcpfilesend/.vscode/settings.json
vendored
Normal file
31
cpp/demo/tcpfilesend/.vscode/settings.json
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
{
|
||||
"files.autoSave": "onFocusChange",
|
||||
"editor.fontSize": 14,
|
||||
"editor.fontFamily": "'Cascadia Code', 'Cascadia Code', 'Cascadia Code'",
|
||||
"cmake.configureOnOpen": true,
|
||||
"cmake.debugConfig": {
|
||||
//"externalConsole": true,
|
||||
"setupCommands": [
|
||||
{
|
||||
"description": "-gdb-set charset utf-8",
|
||||
"text": "-gdb-set charset UTF-8"
|
||||
},
|
||||
{
|
||||
"description": "Enable gdb pretty-printing",
|
||||
"text": "-enable-pretty-printing",
|
||||
"ignoreFailures": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"editor.inlayHints.enabled": "off",
|
||||
"C_Cpp.intelliSenseEngine": "disabled",
|
||||
"clangd.arguments": [
|
||||
"--clang-tidy",
|
||||
"-j=4",
|
||||
"--pch-storage=memory",
|
||||
"--compile-commands-dir=build",
|
||||
"--background-index",
|
||||
"--ranking-model=heuristics",
|
||||
"--query-driver=E:/program/mingw64/bin/g++.exe"
|
||||
]
|
||||
}
|
11
cpp/demo/tcpfilesend/CMakeLists.txt
Normal file
11
cpp/demo/tcpfilesend/CMakeLists.txt
Normal file
@ -0,0 +1,11 @@
|
||||
cmake_minimum_required (VERSION 3.8)
|
||||
|
||||
project (tcpfilesend)
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
|
||||
add_executable(tcpfilesend main.cpp)
|
||||
add_executable(tcpfileserver server.cpp)
|
||||
add_executable(tcpfileserver2 server2.cpp)
|
||||
target_link_libraries(tcpfilesend ws2_32)
|
||||
target_link_libraries(tcpfileserver ws2_32)
|
||||
target_link_libraries(tcpfileserver2 ws2_32)
|
89
cpp/demo/tcpfilesend/main.cpp
Normal file
89
cpp/demo/tcpfilesend/main.cpp
Normal file
@ -0,0 +1,89 @@
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <cstdio>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
|
||||
constexpr int BUFFER_SIZE = 4096;
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
if (argc == 1) {
|
||||
std::cout << "Need Param, Example: send 127.0.0.1 9696 E:\\2.bmp\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 初始化Winsock
|
||||
WSADATA wsaData;
|
||||
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
|
||||
std::cerr << "Failed to initialize Winsock." << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 创建套接字
|
||||
SOCKET clientSocket = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (clientSocket == INVALID_SOCKET) {
|
||||
std::cerr << "Failed to create socket." << std::endl;
|
||||
WSACleanup();
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 设置服务器地址
|
||||
sockaddr_in serverAddress{};
|
||||
serverAddress.sin_family = AF_INET;
|
||||
serverAddress.sin_port = htons(std::stoi(std::string(argv[2])));
|
||||
if (inet_pton(AF_INET, argv[1], &(serverAddress.sin_addr)) <= 0) {
|
||||
std::cerr << "Invalid server address." << std::endl;
|
||||
closesocket(clientSocket);
|
||||
WSACleanup();
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 连接到服务器
|
||||
if (connect(clientSocket, reinterpret_cast<sockaddr*>(&serverAddress),
|
||||
sizeof(serverAddress)) == SOCKET_ERROR) {
|
||||
std::cerr << "Failed to connect to server." << std::endl;
|
||||
closesocket(clientSocket);
|
||||
WSACleanup();
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 打开要发送的文件
|
||||
FILE* file = std::fopen(argv[3], "rb");
|
||||
if (!file) {
|
||||
std::cerr << "Failed to open file : " << argv[3] << std::endl;
|
||||
closesocket(clientSocket);
|
||||
WSACleanup();
|
||||
return 1;
|
||||
}
|
||||
|
||||
int Second = 3;
|
||||
std::cout << Second << " Second after to start send .....\n";
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(Second * 1000));
|
||||
// 读取文件内容并发送到服务器
|
||||
size_t allLen = 0;
|
||||
char buffer[BUFFER_SIZE];
|
||||
while (!std::feof(file)) {
|
||||
int nSize = std::fread(buffer, sizeof(char), BUFFER_SIZE, file);
|
||||
if (nSize > 0) {
|
||||
allLen += nSize;
|
||||
|
||||
if (send(clientSocket, buffer, nSize, 0) == SOCKET_ERROR) {
|
||||
std::cerr << "Failed to send data to server." << std::endl;
|
||||
break;
|
||||
}
|
||||
std::cout << "already send Size = " << allLen << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
// 关闭套接字和文件
|
||||
std::fclose(file);
|
||||
closesocket(clientSocket);
|
||||
WSACleanup();
|
||||
|
||||
std::cout << "Send Done, Size = " << allLen << std::endl;
|
||||
return 0;
|
||||
}
|
170
cpp/demo/tcpfilesend/server.cpp
Normal file
170
cpp/demo/tcpfilesend/server.cpp
Normal file
@ -0,0 +1,170 @@
|
||||
#include <WS2tcpip.h>
|
||||
#include <WinSock2.h>
|
||||
|
||||
#include <cstdio>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
|
||||
#define BUFFER_SIZE 1024
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
if (argc == 1) {
|
||||
std::cout << "Need Param, Example: server 127.0.0.1 9696 E:\\2.bmp\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 初始化 Winsock
|
||||
WSADATA wsaData;
|
||||
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
|
||||
std::cerr << "Failed to initialize Winsock." << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 创建套接字
|
||||
SOCKET serverSocket = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (serverSocket == INVALID_SOCKET) {
|
||||
std::cerr << "Failed to create socket: " << WSAGetLastError()
|
||||
<< std::endl;
|
||||
WSACleanup();
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 绑定地址和端口
|
||||
sockaddr_in serverAddr{};
|
||||
serverAddr.sin_family = AF_INET;
|
||||
serverAddr.sin_port = htons(std::stoi(std::string(argv[2])));
|
||||
serverAddr.sin_addr.s_addr = inet_addr(argv[1]);
|
||||
;
|
||||
if (bind(serverSocket, reinterpret_cast<sockaddr*>(&serverAddr),
|
||||
sizeof(serverAddr)) == SOCKET_ERROR) {
|
||||
std::cerr << "Failed to bind socket: " << WSAGetLastError()
|
||||
<< std::endl;
|
||||
closesocket(serverSocket);
|
||||
WSACleanup();
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 监听连接请求
|
||||
if (listen(serverSocket, 1) == SOCKET_ERROR) {
|
||||
std::cerr << "Failed to listen on socket: " << WSAGetLastError()
|
||||
<< std::endl;
|
||||
closesocket(serverSocket);
|
||||
WSACleanup();
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::cout << "server ip: " << argv[1] << " port: " << argv[2] << std::endl;
|
||||
std::cout << "Server started. Waiting for client connection..."
|
||||
<< std::endl;
|
||||
|
||||
// 接受客户端连接
|
||||
SOCKET clientSocket = accept(serverSocket, nullptr, nullptr);
|
||||
if (clientSocket == INVALID_SOCKET) {
|
||||
std::cerr << "Failed to accept client connection: " << WSAGetLastError()
|
||||
<< std::endl;
|
||||
closesocket(serverSocket);
|
||||
WSACleanup();
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::cout << "Client connected. Receiving data..." << std::endl;
|
||||
|
||||
// 创建接收缓冲区
|
||||
char buffer[BUFFER_SIZE];
|
||||
size_t allLen = 0;
|
||||
// 打开文件以保存接收的数据
|
||||
FILE* file = std::fopen(argv[3], "wb");
|
||||
if (!file) {
|
||||
std::cerr << "Failed to open file for writing." << std::endl;
|
||||
closesocket(clientSocket);
|
||||
closesocket(serverSocket);
|
||||
WSACleanup();
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 循环接收数据
|
||||
while (true) {
|
||||
// 创建事件对象
|
||||
WSAEVENT event = WSACreateEvent();
|
||||
if (event == WSA_INVALID_EVENT) {
|
||||
std::cerr << "Failed to create event: " << WSAGetLastError()
|
||||
<< std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
// 将事件对象与套接字关联
|
||||
if (WSAEventSelect(clientSocket, event, FD_READ) == SOCKET_ERROR) {
|
||||
std::cerr << "Failed to associate event with socket: "
|
||||
<< WSAGetLastError() << std::endl;
|
||||
WSACloseEvent(event);
|
||||
break;
|
||||
}
|
||||
|
||||
// 等待事件对象变为 signaled 状态
|
||||
DWORD waitResult =
|
||||
WSAWaitForMultipleEvents(1, &event, FALSE, WSA_INFINITE, FALSE);
|
||||
if (waitResult == WSA_WAIT_FAILED) {
|
||||
std::cerr << "Failed to wait for event: " << WSAGetLastError()
|
||||
<< std::endl;
|
||||
WSACloseEvent(event);
|
||||
break;
|
||||
}
|
||||
|
||||
// 检查事件对象状态
|
||||
if (waitResult == WSA_WAIT_EVENT_0) {
|
||||
WSANETWORKEVENTS networkEvents;
|
||||
if (WSAEnumNetworkEvents(clientSocket, event, &networkEvents) ==
|
||||
SOCKET_ERROR) {
|
||||
std::cerr << "Failed to enumerate network events: "
|
||||
<< WSAGetLastError() << std::endl;
|
||||
WSACloseEvent(event);
|
||||
break;
|
||||
}
|
||||
|
||||
// 检查是否有数据可读
|
||||
if (networkEvents.lNetworkEvents & FD_READ) {
|
||||
if (networkEvents.iErrorCode[FD_READ_BIT] != 0) {
|
||||
std::cerr << "Error in FD_READ: "
|
||||
<< networkEvents.iErrorCode[FD_READ_BIT]
|
||||
<< std::endl;
|
||||
WSACloseEvent(event);
|
||||
break;
|
||||
}
|
||||
|
||||
// 接收数据
|
||||
int bytesRead = recv(clientSocket, buffer, BUFFER_SIZE, 0);
|
||||
if (bytesRead > 0) {
|
||||
// 将数据写入文件
|
||||
std::fwrite(buffer, sizeof(char), bytesRead, file);
|
||||
allLen += bytesRead;
|
||||
std::cout << "already recv: " << allLen << "\n";
|
||||
} else if (bytesRead == 0) {
|
||||
// 客户端关闭连接
|
||||
std::cout << "Client disconnected." << std::endl;
|
||||
WSACloseEvent(event);
|
||||
break;
|
||||
} else {
|
||||
// 发生错误
|
||||
std::cerr << "Failed to receive data: " << WSAGetLastError()
|
||||
<< std::endl;
|
||||
WSACloseEvent(event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WSACloseEvent(event);
|
||||
}
|
||||
|
||||
// 关闭套接字和清理资源
|
||||
closesocket(clientSocket);
|
||||
closesocket(serverSocket);
|
||||
WSACleanup();
|
||||
std::fclose(file);
|
||||
|
||||
std::cout << "Done .... file: " << argv[3] << std::endl;
|
||||
return 0;
|
||||
}
|
125
cpp/demo/tcpfilesend/server2.cpp
Normal file
125
cpp/demo/tcpfilesend/server2.cpp
Normal file
@ -0,0 +1,125 @@
|
||||
#include <WS2tcpip.h>
|
||||
#include <WinSock2.h>
|
||||
|
||||
#include <cstdio>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
|
||||
#define BUFFER_SIZE 1024
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
if (argc == 1) {
|
||||
std::cout << "Need Param, Example: server 127.0.0.1 9696 E:\\2.bmp\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 初始化 Winsock
|
||||
WSADATA wsaData;
|
||||
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
|
||||
std::cerr << "Failed to initialize Winsock." << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 创建套接字
|
||||
SOCKET serverSocket = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (serverSocket == INVALID_SOCKET) {
|
||||
std::cerr << "Failed to create socket: " << WSAGetLastError()
|
||||
<< std::endl;
|
||||
WSACleanup();
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 绑定地址和端口
|
||||
sockaddr_in serverAddr{};
|
||||
serverAddr.sin_family = AF_INET;
|
||||
serverAddr.sin_port = htons(std::stoi(std::string(argv[2])));
|
||||
serverAddr.sin_addr.s_addr = inet_addr(argv[1]);
|
||||
;
|
||||
if (bind(serverSocket, reinterpret_cast<sockaddr*>(&serverAddr),
|
||||
sizeof(serverAddr)) == SOCKET_ERROR) {
|
||||
std::cerr << "Failed to bind socket: " << WSAGetLastError()
|
||||
<< std::endl;
|
||||
closesocket(serverSocket);
|
||||
WSACleanup();
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 监听连接请求
|
||||
if (listen(serverSocket, 1) == SOCKET_ERROR) {
|
||||
std::cerr << "Failed to listen on socket: " << WSAGetLastError()
|
||||
<< std::endl;
|
||||
closesocket(serverSocket);
|
||||
WSACleanup();
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::cout << "server ip: " << argv[1] << " port: " << argv[2] << std::endl;
|
||||
std::cout << "Server started. Waiting for client connection..."
|
||||
<< std::endl;
|
||||
|
||||
// 接受客户端连接
|
||||
SOCKET clientSocket = accept(serverSocket, nullptr, nullptr);
|
||||
if (clientSocket == INVALID_SOCKET) {
|
||||
std::cerr << "Failed to accept client connection: " << WSAGetLastError()
|
||||
<< std::endl;
|
||||
closesocket(serverSocket);
|
||||
WSACleanup();
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::cout << "Client connected. Receiving data..." << std::endl;
|
||||
|
||||
// 创建接收缓冲区
|
||||
char buffer[BUFFER_SIZE];
|
||||
size_t allLen = 0;
|
||||
// 打开文件以保存接收的数据
|
||||
FILE* file = std::fopen(argv[3], "wb");
|
||||
if (!file) {
|
||||
std::cerr << "Failed to open file for writing." << std::endl;
|
||||
closesocket(clientSocket);
|
||||
closesocket(serverSocket);
|
||||
WSACleanup();
|
||||
return 1;
|
||||
}
|
||||
// 循环接收数据
|
||||
while (true) {
|
||||
WSABUF dataBuffer{};
|
||||
dataBuffer.len = BUFFER_SIZE;
|
||||
dataBuffer.buf = buffer;
|
||||
|
||||
DWORD bytesReceived = 0;
|
||||
DWORD flags = 0;
|
||||
|
||||
// 接收数据
|
||||
if (WSARecv(clientSocket, &dataBuffer, 1, &bytesReceived, &flags,
|
||||
nullptr, nullptr) == SOCKET_ERROR) {
|
||||
std::cerr << "Failed to receive data: " << WSAGetLastError()
|
||||
<< std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
// 检查接收到的数据大小
|
||||
if (bytesReceived > 0) {
|
||||
// 将数据写入文件
|
||||
// 将数据写入文件
|
||||
std::fwrite(buffer, sizeof(char), bytesReceived, file);
|
||||
allLen += bytesReceived;
|
||||
std::cout << "already recv: " << allLen << "\n";
|
||||
} else if (bytesReceived == 0) {
|
||||
// 客户端关闭连接
|
||||
std::cout << "Client disconnected." << std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 关闭套接字和清理资源
|
||||
closesocket(clientSocket);
|
||||
closesocket(serverSocket);
|
||||
WSACleanup();
|
||||
std::fclose(file);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user