3、关闭套接字
释放服务
源程序:
【1】服务器端:
头文件:
[cpp]
/*server.h*/
#pragma comment(lib, "WS2_32")
#include <WinSock2.h>
#include <iostream>
#include <assert.h>
#include<Windows.h>
#ifndef COMMONDEF_H
#define COMMONDEF_H
#define MAX_PACKET_SIZE 10240 // 数据包的最大长度,单位是sizeof(char)
#define MAXFILEDIRLENGTH 256 // 存放文件路径的最大长度
#define PORT 4096 // 端口号
//#define SERVER_IP "127.0.0.1" // server端的IP地址
// 各种消息的宏定义
#define INVALID_MSG -1 // 无效的消息标识
#define MSG_FILENAME 1 // 文件的名称
#define MSG_FILELENGTH 2 // 传送文件的长度
#define MSG_CLIENT_READY 3 // 客户端准备接收文件
#define MSG_FILE 4 // 传送文件
#define MSG_SENDFILESUCCESS 5 // 传送文件成功
#define MSG_OPENFILE_ERROR 10 // 打开文件失败,可能是文件路径错误找不到文件等原因
#define MSG_FILEALREADYEXIT_ERROR 11 // 要保存的文件已经存在了
class CCSDef
{
public:
#pragma pack(1) // 使结构体的数据按照1字节来对齐,省空间
// 消息头
struct TMSG_HEADER
{
char cMsgID; // 消息标识
TMSG_HEADER(char MsgID = INVALID_MSG)
: cMsgID(MsgID)
{
}
};
// 请求传送的文件名
// 客户端传给服务器端的是全路径名称
// 服务器传回给客户端的是文件名
struct TMSG_FILENAME : public TMSG_HEADER
{
char szFileName[256]; // 保存文件名的字符数组
TMSG_FILENAME()
: TMSG_HEADER(MSG_FILENAME)
{
}
};
// 传送文件长度
struct TMSG_FILELENGTH : public TMSG_HEADER
{
long lLength;
TMSG_FILELENGTH(long length)
: TMSG_HEADER(MSG_FILELENGTH), lLength(length)
{
}
};
// Client端已经准备好了,要求Server端开始传送文件
struct TMSG_CLIENT_READY : public TMSG_HEADER
{
TMSG_CLIENT_READY()
: TMSG_HEADER(MSG_CLIENT_READY)
{
}
};
// 传送文件
struct TMSG_FILE : public TMSG_HEADER
{
union // 采用union保证了数据包的大小不大于MAX_PACKET_SIZE * sizeof(char)
{
char szBuff[MAX_PACKET_SIZE];
struct
{
int nStart;
int nSize;
char szBuff[MAX_PACKET_SIZE - 2 * sizeof(int)];
}tFile;
};
TMSG_FILE()
: TMSG_HEADER(MSG_FILE)
{
}
};
// 传送文件成功
struct TMSG_SENDFILESUCCESS : public TMSG_HEADER
{
TMSG_SENDFILESUCCESS()
: TMSG_HEADER(MSG_SENDFILESUCCESS)
{
}
};
// 传送出错信息,包括:
// MSG_OPENFILE_ERROR:打开文件失败
// MSG_FILEALREADYEXIT_ERROR:要保存的文件已经存在了
struct TMSG_ERROR_MSG : public TMSG_HEADER
{
TMSG_ERROR_MSG(char cErrorMsg)
: TMSG_HEADER(cErrorMsg)
{
}
};
#pragma pack()
};
#endif
cpp文件:
[cpp]
/*Server.cpp*/
#include"Server.h"
char g_szNewFileName[MAXFILEDIRLENGTH];
char g_szBuff[MAX_PACKET_SIZE + 1];
long g_lLength;
char* g_pBuff = NULL;
//初始化socket库
bool InitSocket();
//关闭socket库
bool CloseSocket();
//解析消息并进行相应的处理
bool ProcessMsg(SOCKET sClient);
//监听Client消息
void ListenToClient();
//打开文件
bool OpenFile(CCSDef::TMSG_HEADER* pMagHeader,SOCKET sClient);
//传送文件
bool SendFile(SOCKET sClient);
//读取文件进缓冲区
bool ReadFile(SOCKET sClient);
int main()
{
while(1)
{
InitSocket();
ListenToClient();
CloseSocket();
system("del E:\\test1.A_exp");
}
//system("pause");
return 0;
}
//初始化socket库
bool InitSocket()
{
WSADATA wsaData;
WORD socketVersion=MAKEWORD(2,2);
if(::WSAStartup(socketVersion,&wsaData)!=0)
{//初始化WinSock服务
printf("Init socket dll error\n");
return false;
}
return true;
}
//关闭socket库
bool CloseSocket()
{//释放winsock库
::WSACleanup();
if(g_pBuff != NULL)
{
delete [] g_pBuff;
g_pBuff = NULL;
}
return true;
}
//解析消息并进行相应的处理
bool ProcessMsg(SOCKET sClient)
{
//从套接口中接收数据,返回copy的字节数
int nRecv = ::recv(sClient,g_szBuff,MAX_PACKET_SIZE+1,0);
if(nRecv>0)
{
g_szBuff[nRecv]='\0';
}
//解析命令
CCSDef::TMSG_HEADER* pMsgHeader=(CCSDef::TMSG_HEADER*)g_szBuff;
switch(pMsgHeader->cMsgID)
{
case MSG_FILENAME://文件名
{
OpenFile(pMsgHeader,sClient);
}
break;
case MSG_CLIENT_READY://客户端已准备完毕,开始传送文件
{
SendFile(sClient);
}
break;
case MSG_SENDFILESUCCESS://传送文件成功
{
printf("Send File Success!\n");
return false;
}
break;
case MSG_FILEALREADYEXIT_ERROR://要保存的文件已经存在
{
printf("The file ready to send already exit!\n");
return false;
}
break;
}
return true;
}
//监听Client消息
void ListenToClient()
{
//创建套接字
SOCKET sListen = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(sListen == SOCKET_ERROR)
{
printf("Init Socket Error!\n");
return;
}
//绑定socket
sockaddr_in sin;
sin.sin_family=AF_INET;
sin.sin_port=htons(PORT);
sin.sin_addr.S_un.S_addr=INADDR_ANY;
if (::bind(sListen, (LPSOCKADDR)&sin, sizeof(sockaddr_in)) == SOCKET_ERROR)
{
printf("Bind Error!\n");
return;
}
// 设置socket进入监听状态
if(::listen(sListen,10)==SOCKET_ERROR)
{
printf("Listen Error!\n");
return;
}