windows 下TCP通信,采用多线程,server和client可以自由的发送和接受消息。同时client可以进行文件的下载,纯c++代码
//client
#include
#include
#include
#include
#include
#define MAX_BUF 8*1024
using namespace std;
#pragma comment(lib,"ws2_32.lib")
enum MSG_TYPE {
DOWNLOAD_START,
DOWNLOAD_SURE,
DOWNLOAD_END,
DOWNLOAD,
DOWNLOAD_STOP,
};
SOCKET sock=-1;
fstream *outfile=nullptr;
bool ConnectServer();
bool SendPacket(long type = DOWNLOAD, string packet = "");
void ReceiveMsgJudge(string buf);
void RecvData();
void Run();
void DownloadStart(string _name,long long speeh=100*1024);//speeh is 100k
void Downloading(string data);
void DownloadEnd();
int main(){
thread RecvThread(RecvData);
RecvThread.detach();
thread SendThread(Run);
SendThread.join();
return 0;
}
bool ConnectServer(){
WORD sockVersion = MAKEWORD(2, 2);
WSADATA data;
if (WSAStartup(sockVersion, &data) != 0)return false;
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET) {
cout << "Socket error" << endl;
WSACleanup();
return false;
}
sockaddr_in sock_in;
sock_in.sin_family = AF_INET;
sock_in.sin_port = htons(8888);
sock_in.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
if (connect(sock, (sockaddr*)&sock_in, sizeof(sock_in)) == SOCKET_ERROR) {
cout << "Connect error" << endl;
WSACleanup();
return false;
}
std::cout<<"connect succeed :\t"<<std::endl;
return true;
}
bool SendPacket(long type, string packet) {
long len = packet.size() + sizeof(type);
char *sendBuf = new char[len];
memset(sendBuf, 0, len);
memcpy(sendBuf, &type, sizeof(long));
memcpy(sendBuf + sizeof(type), packet.c_str(), packet.size());
send(sock, sendBuf, len, 0);
delete[] sendBuf;
return true;
}
void ReceiveMsgJudge(string buf){
long _type =0;
memcpy(&_type, buf.c_str(), sizeof(long));
string data = buf.substr(sizeof(long), buf.size() - sizeof(long));
switch (_type) {
case MSG_TYPE::DOWNLOAD_START: {
std::cout << "recv download start beg :\t" << data << std::endl;
outfile=new fstream("./download/"+data, ios::out|ios::binary);
if (!outfile->good())SendPacket(DOWNLOAD_END, "false");
else SendPacket(DOWNLOAD_SURE,"start");
break;
}
case MSG_TYPE::DOWNLOAD: {
Downloading(data);
break;
}
case MSG_TYPE::DOWNLOAD_END: {
std::cout << "recv download end :\t" << data << std::endl;
DownloadEnd();
break;
}
case MSG_TYPE::DOWNLOAD_STOP: {
break;
}
case MSG_TYPE::DOWNLOAD_SURE: {
break;
}
default: {
std::cout << "test data:\t" << data << std::endl;
}
}
}
void RecvData(){
string data;
char recv_buf[MAX_BUF] = { 0 };
while(1){
int len = ::recv(sock, recv_buf, MAX_BUF, 0);
if (len >0) {
string data(recv_buf, len);
ReceiveMsgJudge(data);
}
else {
std::cout<<"socket close,try connect again :\t" <<std::endl;
closesocket(sock);
WSACleanup();
ConnectServer();
}
}
}
void Run(){
string command;
while (1) {
cin >> command;
SendPacket(DOWNLOAD_START, command);
}
}
void DownloadStart(string _name, long long speeh){
string data = _name +">>"+ std::to_string(speeh);
SendPacket(DOWNLOAD_START,data);
}
void Downloading(string data){
if (outfile == nullptr) {
SendPacket(DOWNLOAD_END);
return;
}
std::cout<<"recv file data :\t"<<outfile->tellp() <<std::endl;
outfile->write(data.c_str(), data.size());
}
void DownloadEnd(){
if (outfile == nullptr) {
}
else {
if (outfile->is_open())outfile->close();
delete outfile;
outfile = nullptr;
}
std::cout<<"download write end\t" <<std::endl;
}
//server
#include
#include
#include
#include
#include
#include
#define MAX_BUF 8*1024
using namespace std;
#pragma comment(lib,"ws2_32.lib")
enum MSG_TYPE {
DOWNLOAD_START,
DOWNLOAD_SURE,
DOWNLOAD_END,
DOWNLOAD,
DOWNLOAD_STOP,
};
fstream* in_file = nullptr;
SOCKET server_socket = -1;
SOCKET client_socket = -1;
string GetFileName(string data) {
regex pa("\\\\{1,}");
data=std::regex_replace(data, pa, "/");
std::cout<<" :\t"<<data <<std::endl;
data = data.substr(data.find_last_of("/") + 1);
return data;
}
bool SendPacket(long type = DOWNLOAD, string packet = "");
void DownloadStart(string buf);
void DownloadEnd(string data="");
void Downloading();
void ReceiveMsgJudge(string buf);
void RunServer();
void Run();
int main(int argc, char* argv[]) {
thread RecvThread(RunServer);
RecvThread.detach();
thread SendThread(Run);
SendThread.join();
return 0;
}
bool SendPacket(long type, string packet) {
long len = packet.size() + sizeof(type);
char *sendBuf = new char[len];
memset(sendBuf, 0, len);
memcpy(sendBuf, &type, sizeof(long));
memcpy(sendBuf + sizeof(type), packet.c_str(), packet.size());
send(client_socket,sendBuf,len,0);
delete [] sendBuf;
return true;
};
void DownloadStart(string buf) {
if (in_file != nullptr) {
SendPacket(DOWNLOAD_END, "true");
}
else {
string file_name = buf;
in_file = new fstream(file_name, ios::in|ios::binary);
file_name = GetFileName(file_name);
if (in_file->good()) {
SendPacket(DOWNLOAD_START, file_name);
}
else {
DownloadEnd("open file fail");
}
}
}
void DownloadEnd(string data) {
if (in_file != nullptr) {
if (in_file->is_open())in_file->close();
delete in_file;
in_file = nullptr;
}
std::cout << "download read end ,result is :\t" <<data<< std::endl;
SendPacket(DOWNLOAD_END,data);
}
void Downloading() {
if (in_file == nullptr) {
SendPacket(DOWNLOAD_END);
return;
}
char readBuf[MAX_BUF-sizeof(long)] = { 0 };
while (!in_file->eof()) {
memset(readBuf, 0, MAX_BUF - sizeof(long));
in_file->read(readBuf, MAX_BUF - sizeof(long));
string data(readBuf, in_file->gcount());
SendPacket(DOWNLOAD, data);
Sleep(500);
//std::cout<<"send len :\t"<tellg() <
}
DownloadEnd("Server send all");
SendPacket(DOWNLOAD_END);
}
void ReceiveMsgJudge(string buf) {
long _type = 0;
memcpy(&_type, buf.c_str(), sizeof(long));
string data = buf.substr(sizeof(long), buf.size() - sizeof(long));
switch (_type) {
case MSG_TYPE::DOWNLOAD_START: {
std::cout<<"recv download start :\t"<<data <<std::endl;
DownloadStart(data);
break;
}
case MSG_TYPE::DOWNLOAD: {
break;
}
case MSG_TYPE::DOWNLOAD_END: {
DownloadEnd("recv client download end");
break;
}
case MSG_TYPE::DOWNLOAD_STOP: {
break;
}
case MSG_TYPE::DOWNLOAD_SURE: {
Downloading();
break;
}
default: {
std::cout << "test data:\t" << data << std::endl;
}
}
}
void RunServer() {
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
server_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
sockaddr_in sockAddr;
sockAddr.sin_family = AF_INET;
sockAddr.sin_port = htons(8888);
sockAddr.sin_addr.S_un.S_addr = INADDR_ANY;
//bind
if (::bind(server_socket, (sockaddr*)&sockAddr, sizeof(sockAddr)) == SOCKET_ERROR) {
cout << "Bind error" << endl;
printf("error=%d\n", WSAGetLastError());
WSACleanup();
return ;
}
//listen number max is 1
if (listen(server_socket, 1) == SOCKET_ERROR) {
cout << "Listen error" << endl;
WSACleanup();
return ;
}
//accept client
sockaddr_in client_sin;
int len = sizeof(client_sin);
client_socket = accept(server_socket, (sockaddr*)&client_sin, &len);
if (client_socket == INVALID_SOCKET) {
WSACleanup();
return;
}
else {
//std::cout<<"start recv :\t"<
//start recv
char recvBuf[MAX_BUF] = { 0 };
while (1) {
int num = recv(client_socket, recvBuf, MAX_BUF, 0);
if (num > 0) {
string data(recvBuf, num);
ReceiveMsgJudge(data);
}
else {
cout << "Client leave" << endl;
closesocket(client_socket);
client_socket = accept(server_socket, (sockaddr*)&client_sin, &len);
std::cout<<"have client accept :\t" <<std::endl;
}
}
}
}
void Run(){
string command;
while (1) {
cin >> command;
SendPacket(9, command);
}
}