Server(多连接客户发送)
#include "stdafx.h"
#include "iostream"
#include "fstream"
#include "process.h" //使用C++运行库中的函数创建多线程
#include "winsock2.h"
#define PORT 65432 //定义服务器的监听端口号
#pragma comment(lib,"ws2_32.lib")
using namespace std;
char Command[20]="";//存放从键盘接收到的结束命令
char filename[128]; //存放从键盘输入的含有信息的文件名
char fname[128]; //存放发送给客户端的无路径信息的文件名
ifstream inFile; //定义文件输入流
unsigned int _stdcall GetCommand(void *par); //声明输入close命令的线程函数
unsigned int _stdcall SendFile(void *par); //声明发送文件的线程函数
int main()
{
/***定义相关的变量***/
int sock_server;
struct sockaddr_in addr,client_addr;
unsigned hThread1, hThread2;
unsigned int ThreadID1,ThreadID2;
int addr_len = sizeof(struct sockaddr_in);
cout<<"请输入要发送的文件名:\n";
cin>>filename;
/***以二进制读方式打开要分发的文件***/
inFile.open(filename, ios::in|ios::binary);//打开文件
if(!inFile.is_open())
{
cout<<"Cannot open "<<filename<<endl;
return 0; //文件打开失败则退出
}
/***截取发送给客户端的文件名***/
int len=strlen(filename);
int i=len;
while(filename[i]!='\\' && i>=0)i--;
if(i<0) i=0; else i++;
int m=0;
while(filename[m+i]!='\0')
{
fname[m]=filename[m+i];
m++;
}
/***初始化winsock DLL***/
WSADATA wsaData;
WORD wVersionRequested=MAKEWORD(2,2); //生成版本号
if(WSAStartup(wVersionRequested,&wsaData)!=0)
{
cout<<"加载winsock.dll失败!\n";
return 0;
}
/***创建套接字***/
if ((sock_server = socket(AF_INET,SOCK_STREAM,0))<0) //建立一个socket
{
cout<<"创建套接字失败!\n";
WSACleanup();
return 0;
}
/***设置套接字为非阻塞模式***/
unsigned long ul =1; //设置套接字选项参数
int nRet = ioctlsocket(sock_server, FIONBIO, (unsigned long*)&ul);
if (nRet == SOCKET_ERROR)
{
cout<<"设置套接字选项失败!\n";
closesocket(sock_server);
WSACleanup();
return 0;
}
/***绑定IP端口***/
memset((void *)&addr,0,addr_len);
addr.sin_family =AF_INET;
addr.sin_port = htons(PORT);
addr.sin_addr.s_addr = htonl(INADDR_ANY);//使用本机的所有IP地址
if(bind(sock_server,(LPSOCKADDR)&addr,sizeof(addr))!=0)
{
cout<<"绑定地址失败!\n";
closesocket(sock_server);
WSACleanup();
return 0;
}
/***开始监听***/
if(listen(sock_server,5)!=0)
{
cout<<"listen函数调用失败!\n";
closesocket(sock_server);
WSACleanup();
return 0;
}
else
cout<<"listenning......\n";
/***启动命令接收线程***/
hThread1=_beginthreadex(NULL,0,GetCommand,(LPVOID)Command,0,&ThreadID1);
/***接收并处理客户连接 ***/
SOCKET newsock;
while(1)
{
Sleep(10);
if(strcmp(Command,"close")==0)break ; //如果输入close命令则退出
newsock = accept(sock_server,(LPSOCKADDR)&client_addr,&addr_len);
if(newsock!=INVALID_SOCKET)
{
cout<<"cnnect from "<<inet_ntoa(client_addr.sin_addr)<<endl;
hThread2=_beginthreadex(NULL,0,SendFile,(LPVOID)newsock,0,&ThreadID2);//启动文件发送线程
}
}
inFile.close();
closesocket(sock_server);
return 0;
}
/*****************文件传输线程函数********************************/
unsigned int _stdcall SendFile(void *par)
{
char buffer[1000];
inFile.seekg(0,ios::beg);//将文件读指针移动到文件头,如果少了本行,第二个客户收到的文件将是0字节
SOCKET sock=(SOCKET)par;
/***设置套接字为阻塞模式***/
unsigned long ul =0; //设置套接字选项
int nRet = ioctlsocket(sock, FIONBIO, (unsigned long*)&ul);
send(sock,(char*)fname,strlen(fname)+1,0); //发送文件名
int size=recv(sock,buffer,sizeof(buffer),0); //接收对方发来的“OK”消息
cout<<buffer<<endl;
if(strcmp(buffer,"OK")!=0)
{
cout<<"客户端出错!\n";
closesocket(sock); //关闭socket
return 0;
}
/****传输文件内容****/
while(!inFile.eof())
{
inFile.read(buffer,sizeof(buffer));
size=inFile.gcount(); //获取实际读取的字节数
send(sock,(char*)buffer,size,0);
}
cout<<"文件传输结束!\n";
closesocket(sock); //关闭socket
return 0;
}
/*************从键盘接收命令的线程函数********************/
unsigned int _stdcall GetCommand(void *par)
{
char * p=(char *)par;
while(strcmp(p,"close")!=0)
{Sleep(10);gets(p);}
return 0;
}
TCP多线程客户传输文件
于 2021-11-16 16:03:17 首次发布