请用C++winsock2写一个TCP/IP文件传输(指定ip和端口)的客户端和服务器的完整实例
时间: 2024-09-08 19:04:02 浏览: 226
bind实例-TCP-IP+Socket网络编程
C++的Winsock2库主要用于Windows平台下的网络编程,包括TCP/IP协议。以下是一个简单的TCP/IP文件传输的客户端和服务器的例子,假设我们只处理文本文件的上传和下载:
**服务器端(server.cpp):**
```cpp
#include <winsock2.h>
#include <ws2tcpip.h>
#include <iostream>
#include <fstream>
#pragma comment(lib, "Ws2_32.lib")
const char* serverIP = "127.0.0.1";
int serverPort = 9000;
// 创建套接字、绑定地址、监听等
SOCKET serverSocket;
void initServer() {
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
std::cerr << "Error initializing Winsock." << std::endl;
return;
}
serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (serverSocket == INVALID_SOCKET) {
std::cerr << "Error creating socket." << std::endl;
WSACleanup();
return;
}
sockaddr_in serverAddr;
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = inet_addr(serverIP);
serverAddr.sin_port = htons(serverPort);
if (bind(serverSocket, (SOCKADDR*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {
std::cerr << "Error binding to address." << std::endl;
closesocket(serverSocket);
WSACleanup();
return;
}
listen(serverSocket, SOMAXCONN); // 监听连接
std::cout << "Server listening on " << serverIP << ":" << serverPort << std::endl;
}
// 处理客户端请求
void handleClient(SOCKET clientSocket) {
char buffer[1024];
int bytesRead;
while ((bytesRead = recv(clientSocket, buffer, sizeof(buffer), 0)) > 0) {
std::string message(buffer, bytesRead);
if (message == "upload") { // 接收上传指令
std::ifstream file("file.txt", std::ios::binary);
if (file.is_open()) {
send(clientSocket, "Upload started.", strlen("Upload started."), 0);
std::copy(file.rdbuf(), file.rdbuf() + file.gcount(), buffer);
send(clientSocket, buffer, file.gcount(), 0);
file.close();
} else {
send(clientSocket, "File not found.", strlen("File not found."), 0);
}
} else if (message == "download") { // 接收下载指令
send(clientSocket, "Downloading...", strlen("Downloading..."), 0);
std::ofstream outputFile("file.txt", std::ios::binary | std::ios::out);
if (!outputFile) {
send(clientSocket, "Failed to create output file.", strlen("Failed to create output file."), 0);
} else {
sendfile(clientSocket, stdout, NULL, -1, NULL, NULL);
outputFile.close();
send(clientSocket, "Download completed.", strlen("Download completed."), 0);
}
} else {
send(clientSocket, "Unknown command.", strlen("Unknown command."), 0);
}
}
if (bytesRead == 0 || bytesRead == -1) { // 错误或关闭
shutdown(clientSocket, SD_SEND);
closesocket(clientSocket);
}
}
int main() {
initServer();
while (true) {
SOCKET clientSocket = accept(serverSocket, NULL, NULL);
if (clientSocket == INVALID_SOCKET) {
break; // 处理错误
}
std::cout << "Accepted connection from " << inet_ntoa(((sockaddr_in*)getpeername(clientSocket))->sin_addr) << "." << std::endl;
handleClient(clientSocket);
}
closesocket(serverSocket);
WSACleanup();
return 0;
}
```
**客户端(client.cpp):**
```cpp
#include <winsock2.h>
#include <ws2tcpip.h>
#include <iostream>
const char* serverIP = "127.0.0.1";
int serverPort = 9000;
void connectToServer() {
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
std::cerr << "Error initializing Winsock." << std::endl;
return;
}
SOCKET clientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (clientSocket == INVALID_SOCKET) {
std::cerr << "Error creating socket." << std::endl;
WSACleanup();
return;
}
sockaddr_in serverAddr;
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = inet_addr(serverIP);
serverAddr.sin_port = htons(serverPort);
if (connect(clientSocket, (SOCKADDR*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {
std::cerr << "Error connecting to server." << std::endl;
closesocket(clientSocket);
WSACleanup();
return;
}
std::string command;
std::getline(std::cin, command);
switch (command[0]) {
case 'u': // 上传
std::ifstream file("file.txt", std::ios::binary);
if (file.is_open()) {
send(clientSocket, "Uploading...", strlen("Uploading..."), 0);
std::copy(file.rdbuf(), file.rdbuf() + file.gcount(), buffer);
send(clientSocket, buffer, file.gcount(), 0);
file.close();
std::cout << "Uploaded successfully.\n";
} else {
std::cerr << "File not found.\n";
}
break;
case 'd': // 下载
std::ofstream outputFile("file.txt", std::ios::binary | std::ios::out);
if (!outputFile) {
std::cerr << "Failed to create output file.\n";
} else {
send(clientSocket, "Downloading...\n", strlen("Downloading...\n"), 0);
sendfile(clientSocket, outputFile.getHandle(), NULL, -1, NULL, NULL);
outputFile.close();
std::cout << "Downloaded successfully.\n";
}
break;
default:
std::cerr << "Invalid command.\n";
break;
}
closesocket(clientSocket);
WSACleanup();
}
int main() {
connectToServer();
return 0;
}
```
注意:这是一个简化的示例,实际应用需要处理更多的边界情况,并添加异常处理和错误消息。同时,`sendfile`函数用于高效的文件传输。
阅读全文