//****************************客户端*****************************************************************
#include "SocketClient.h"
#pragma once
//WinSock必须的头文件和库
#include <WinSock2.h>
#pragma comment(lib,"ws2_32.lib")
//辅助头文件
#include <assert.h>
//网络数据类型
#define TCP_DATA 1
#define UDP_DATA 2
//TCP连接限制
#define MAX_TCP_CONNECT 10
//缓冲区上限
#define MAX_BUFFER_LEN 1024
class CSocketClient
{
//******************************
int m_type;//通信协议类型
SOCKET m_socket;//本地套接字
sockaddr_in serverAddr;//服务器地址结构
//******************************
public:
int init(int inet_type,char*addr,unsigned short port);//初始化通信协议,地址,端口
char *getProto();//获取通信协议类型
char *getIP();//获取IP地址
unsigned short getPort();//获取端口
void sendData(const char * buff,const int len);//发送数据
void getData(char * buff,const int len);//接收数据
CSocketClient(void);
~CSocketClient(void);
void close(void);
};
//**********************************客户端CPP文件***************************************************
#include "StdAfx.h"
#include "SocketClient.h"
CSocketClient::CSocketClient(void)
{
WSADATA wsa;
int rslt=WSAStartup(WINSOCK_VERSION,&wsa);//加载WinSock DLL
assert(rslt==0);
}
int CSocketClient::init(int inet_type,char*addr,unsigned short port)
{
int rslt;
m_type=inet_type;
if(m_type==TCP_DATA)//TCP数据
m_socket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);//创建TCP套接字
else if(m_type==UDP_DATA)//UDP数据
m_socket=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);//创建UDP套接字
// assert(m_socket!=INVALID_SOCKET);
serverAddr.sin_family=AF_INET;
serverAddr.sin_addr.S_un.S_addr=inet_addr(addr);
serverAddr.sin_port=htons(port);
memset(serverAddr.sin_zero,0,8);
if(m_type==TCP_DATA)//TCP数据
{
rslt=connect(m_socket,(sockaddr*)&serverAddr,sizeof(sockaddr));//客户端连接请求
// assert(rslt==0);
}
return rslt;
}
void CSocketClient::sendData(const char * buff,const int len)
{
int rslt;
int addrLen=sizeof(sockaddr_in);
// memset(buff,0,len);
if(m_type==TCP_DATA)//TCP数据
{
rslt=send(m_socket,buff,len,0);
}
else if(m_type==UDP_DATA)//UDP数据
{
rslt=sendto(m_socket,buff,len,0,(sockaddr*)&serverAddr,addrLen);
}
//assert(rslt>0);
}
void CSocketClient::getData(char * buff,const int len)
{
int rslt;
int addrLen=sizeof(sockaddr_in);
memset(buff,0,len);
if(m_type==TCP_DATA)//TCP数据
{
rslt=recv(m_socket,buff,len,0);
}
else if(m_type==UDP_DATA)//UDP数据
{
rslt=recvfrom(m_socket,buff,len,0,(sockaddr*)&serverAddr,&addrLen);
}
//assert(rslt>0);
}
char *CSocketClient::getProto()
{
if(m_type==TCP_DATA)
return "TCP";
else if(m_type==UDP_DATA)
return "UDP";
else
return "";
}
char *CSocketClient::getIP()
{
return inet_ntoa(serverAddr.sin_addr);
}
unsigned short CSocketClient::getPort()
{
return ntohs(serverAddr.sin_port);
}
CSocketClient::~CSocketClient(void)
{
if(m_socket!=INVALID_SOCKET)
closesocket(m_socket);
WSACleanup();//卸载WinSock DLL
}
void CSocketClient::close(void)
{
if(m_socket!=INVALID_SOCKET)
closesocket(m_socket);
}
//======================================================================================
//***************************************************服务器端****************************************************************************
#include "Cserver.h"
#pragma once
#include <WinSock2.h>
#pragma comment(lib,"ws2_32.lib")
//辅助头文件
#include <assert.h>
//网络数据类型
#define TCP_DATA 1
#define UDP_DATA 2
//TCP连接限制
#define MAX_TCP_CONNECT 10
//缓冲区上限
#define MAX_BUFFER_LEN 1024
#include <list>
using namespace std;
class Cserver
{
CRITICAL_SECTION *cs;//临界区对象
int m_type;//记录数据包类型
SOCKET m_socket;//本地socket
sockaddr_in serverAddr;//服务器地址
list<sockaddr_in*> clientAddrs;//客户端地址结构列表
sockaddr_in* addClient(sockaddr_in client);//添加客户端地址结构
void delClient(sockaddr_in *client);//删除客户端地址结构
friend DWORD WINAPI threadProc(LPVOID lpParam);//线程处理函数作为友元函数
public:
Cserver();
void init(int inet_type,char*addr,unsigned short port);
void start();//启动服务器
char* getProto();//获取协议类型
char* getIP(sockaddr_in*serverAddr=NULL);//获取IP
unsigned short getPort(sockaddr_in*serverAddr=NULL);//获取端口
virtual void connect(sockaddr_in*client);//连接时候处理
virtual int procRequest(sockaddr_in*client,const char* req,int reqLen,char*resp);//处理客户端请求
virtual void disConnect(sockaddr_in*client);//断开时候处理
virtual ~Cserver(void);
};
//***************************************************服务器端CPP文件****************************************************************************
#include "StdAfx.h"
#include "Cserver.h"
#include <iostream>
struct SockParam
{
SOCKET rsock;//远程的socket
sockaddr_in *raddr;//远程地址结构
Cserver*pServer;//服务器对象指针
SockParam(SOCKET rs,sockaddr_in*ra,Cserver*ps)
{
rsock=rs;
raddr=ra;
pServer=ps;
}
};
static int i=0;
Cserver::Cserver(void)
{
cs=new CRITICAL_SECTION();
InitializeCriticalSection(cs);//初始化临界区
WSADATA wsa;
int rslt=WSAStartup(WINSOCK_VERSION,&wsa);//加载WinSock DLL
assert(rslt==0);
}
void Cserver::init(int inet_type,char*addr,unsigned short port)
{
int rslt;
m_type=inet_type;
if(m_type==TCP_DATA)//TCP数据
m_socket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);//创建TCP套接字
else if(m_type==UDP_DATA)//UDP数据
m_socket=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);//创建UDP套接字
assert(m_socket!=INVALID_SOCKET);
serverAddr.sin_family=AF_INET;
serverAddr.sin_addr.S_un.S_addr=inet_addr(addr);
serverAddr.sin_port=htons(port);
memset(serverAddr.sin_zero,0,8);
rslt=bind(m_socket,(sockaddr*)&serverAddr,sizeof(serverAddr));//绑定地址和端口
assert(rslt==0);
if(m_type==TCP_DATA)//TCP需要侦听
{
rslt=listen(m_socket,MAX_TCP_CONNECT);//监听客户端连接
assert(rslt==0);
}
}
void Cserver::start()
{
int rslt;
sockaddr_in client;//客户端地址结构
int addrLen=sizeof(client);
SOCKET clientSock;//客户端socket
char buff[MAX_BUFFER_LEN];//UDP数据缓存
while(true)
{
if(m_type==TCP_DATA)//TCP数据
{
clientSock=accept(m_socket,(sockaddr*)&client,&addrLen);//接收请求
if(clientSock==INVALID_SOCKET)
break;
assert(clientSock!=INVALID_SOCKET);
sockaddr_in*pc=addClient(client);//添加一个客户端
connect(pc);//连接处理函数
SockParam sp(clientSock,pc,this);//参数结构
HANDLE thread=CreateThread(NULL,0,threadProc,(LPVOID)&sp,0,NULL);//创建连接线程
assert(thread!=NULL);
CloseHandle(thread);//关闭线程
}
else if(m_type==UDP_DATA)//UDP数据
{
memset(buff,0,MAX_BUFFER_LEN);
rslt=recvfrom(m_socket,buff,MAX_BUFFER_LEN,0,(sockaddr*)&client,&addrLen);
assert(rslt>0);
char resp[MAX_BUFFER_LEN]={0};//接收处理后的数据
rslt=procRequest(&client,buff,rslt,resp);//处理请求
rslt=sendto(m_socket,resp,rslt,0,(sockaddr*)&client,addrLen);//发送udp数据
}
}
}
char* Cserver::getProto()
{
if(m_type==TCP_DATA)
return "TCP";
else if(m_type==UDP_DATA)
return "UDP";
else
return "";
}
char* Cserver::getIP(sockaddr_in*addr)
{
if(addr==NULL)
addr=&serverAddr;
return inet_ntoa(addr->sin_addr);
}
unsigned short Cserver::getPort(sockaddr_in*addr)
{
if(addr==NULL)
addr=&serverAddr;
return htons(addr->sin_port);
}
sockaddr_in* Cserver::addClient(sockaddr_in client)
{
sockaddr_in*pc=new sockaddr_in(client);
clientAddrs.push_back(pc);
return pc;
}
void Cserver::delClient(sockaddr_in *client)
{
assert(client!=NULL);
delete client;
clientAddrs.remove(client);
}
void Cserver::connect(sockaddr_in*client)
{
cout<<"客户端"<<getIP(client)<<"["<<getPort(client)<<"]"<<"连接。"<<endl;
}
int Cserver::procRequest(sockaddr_in*client,const char* req,int reqLen,char*resp)
{
cout<<getIP(client)<<"["<<getPort(client)<<"]:"<<req<<endl;
if(m_type==TCP_DATA)
{
if (i==1)
{
strcpy(resp,"TCP第二次回复");
}
else
{
i++;
strcpy(resp,"TCP第一次回复");
}
}
else if(m_type==UDP_DATA)
strcpy(resp,"UDP回复");
return 15;
}
void Cserver::disConnect(sockaddr_in*client)
{
cout<<"客户端"<<getIP(client)<<"["<<getPort(client)<<"]"<<"断开。"<<endl;
}
Cserver::~Cserver(void)
{
for(list<sockaddr_in*>::iterator i=clientAddrs.begin();i!=clientAddrs.end();++i)//清空客户端地址结构
{
delete *i;
}
clientAddrs.clear();
if(m_socket!=INVALID_SOCKET)
closesocket(m_socket);//关闭服务器socket
WSACleanup();//卸载WinSock DLL
DeleteCriticalSection(cs);
delete cs;
}
DWORD WINAPI threadProc(LPVOID lpParam)//TCP线程处理函数
{
SockParam sp=*(SockParam*)lpParam;
Cserver*s=sp.pServer;
SOCKET sock=s->m_socket;
SOCKET clientSock=sp.rsock;
sockaddr_in *clientAddr=sp.raddr;
CRITICAL_SECTION*cs=s->cs;
int rslt;
char req[MAX_BUFFER_LEN+1]={0};//数据缓冲区,多留一个字节,方便输出
do
{
rslt=recv(clientSock,req,MAX_BUFFER_LEN,0);//接收数据
if(rslt<=0)
break;
char resp[MAX_BUFFER_LEN]={0};//接收处理后的数据
EnterCriticalSection(cs);
rslt=s->procRequest(clientAddr,req,rslt,resp);//处理后返回数据的长度
LeaveCriticalSection(cs);
assert(rslt<=MAX_BUFFER_LEN);//不会超过MAX_BUFFER_LEN
//rslt=send(clientSock,resp,rslt,0);//发送tcp数据
rslt=send(clientSock,resp,rslt,0);//发送tcp数据
}
while(rslt!=0||rslt!=SOCKET_ERROR);
s->delClient(clientAddr);
s->disConnect(clientAddr);//断开连接后处理
return 0;
}