添加一个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