- 论坛徽章:
- 0
|
最近正在做一个项目 有一个小模块 是做 一个 socket通讯 ,我以前很少做过这方面的工作,不知道自己设计的 c++封装类 是否 合理 。
源代码 后附
我的设计思路是这样的
1.交互协议
首先定义数据传送的格式:
typedef struct DataHead{
int MSG;
int data_total_length;
int data_package_length;
}DataHead;
上表达式为数据包头的格式 ,其中内容可以根据需要扩展,
int MSG; 为消息的类型。在发送消息时初始化。
int data_total_length; 为消息的总长 (不包括包头,可为0)为0的话 就没有数据只有包头。
int data_package_length; 为每一次 发送或接受的 包的大小。与total_length 一起配合可以得到整个数据包的接收或者发送的过程。
发送数据包的过程为 先发送数据包头,包头中的total_length,data_package_length。分别规定了包头后的数据长度, 以及接收或者发送的方法。(如果有的数据包过大 可以分几次发送或者接收 ,每次发送data_package_length 长度)
2.类的使用如下
1. Client client("172.31.118.46",65000); 构造客户端交互对象
2. 对DataHead client.m_send_datahead 发送包头进行初试化。
3. 可以使用 client.isconect() 判断是否可以连接成功。
4. 调用 client.sendto(char * date , int total_length)发送数据 如果没有任何数据可以使用 client.sendto(NULL,0); 这样就只发包头过去了。
5.调用client.receive()接受服务器发过来的数据包。返回后 可以从 client. m_recv_datahead 中得到接收到的包头,从 client. m_recvbuf 得到接收到的数据首指针(在堆中) ,从 client. m_recv_length 得到接收数据的长度。
其中可以每一部调用都可以通过 client.isErroe()判断是否有错误产生 ,如有可以通过 client.printerror()打印错误。
我不知道这样做是不是合理 。希望大家给我点指导
Client::Client()
{
m_port = 0 ;
m_socket = -1 ;
bzero(&m_serveraddr,sizeof(m_serveraddr));
m_recvbuf = NULL;
m_errorcode = 0 ;
}
//override constructor
Client::Client(char* ip , int port)
{
int ip_check = 0 ;
m_socket = socket(AF_INET, SOCK_STREAM, 0);
if(m_socket <= 0)
{
setError(ERROR_SOCKET_CREATE);
}
if(port <= 1024 || port > 65535 )
{
setError(ERROR_PORT_SETTING);
}
bzero(&m_serveraddr,sizeof(m_serveraddr));
m_serveraddr.sin_family = AF_INET;
ip_check = inet_addr(ip);
m_serveraddr.sin_port = htons(port);
if(-1 == ip_check)
{
setError(ERROR_IP_SETTING);
return ;
}
m_serveraddr.sin_addr.s_addr = ip_check;
}
bool Client::isError()
{
if(m_errorcode == 0)
return false;
}
void Client::setError(int code)
{
m_errorcode = code;
}
void Client::setIp(char* Ip)
{
}
void Client::setPort(long port)
{
}
//the function can be used to get message form server
//param buf is a char pointer that can store the message which is sent by server
//param n is the maximum length of buf
int Client::receive()
{
if(m_socket == -1)
{
setError(ERROR_SOCKET_CREATE);
return -1;
}
if( recv(m_socket,(char*)&m_recv_datahead,sizeof(DataHead),0) == sizeof(DataHead))
{
int total_length = m_recv_datahead.data_total_length;
if(total_length == 0 )
return 1; //without any data
m_recv_length = total_length;
m_recvbuf = new char[total_length];
int package_length = m_recv_datahead.data_package_length;
int recv_times = total_length/package_length +1;
int i = 1;
int length_left = total_length;
while(i <= recv_times) //three conditions 1. length < packaget 2.length = package*n 3.length > package
{
if(length_left >= package_length) // when the data length is bigger or equril than the package length
{
if(package_length != recv(m_socket, m_recvbuf + (i-1)*package_length ,package_length,0))
{
setError(ERROR_RECV_FAIL);
return -1;
}
}
else
{
if(length_left != 0)
if(length_left != recv(m_socket,m_recvbuf + (i-1)*package_length , length_left,0))
{
setError(ERROR_RECV_FAIL);
return -1;
}
}
length_left = total_length - (i*package_length);
i++;
}
}
else
{
setError(ERROR_RECVHEAD_FAIL);
return -1;
}
return 1;
}
void Client::printerror()
{
}
//
int Client::sendto(char* buf , int n)
{
if(-1 == m_socket )
{
setError(ERROR_SOCKET_CREATE);
return -1;
}
if( n < 0)
{
setError(ERROR_SENDTO_PARAMS_INVAILD);
return -1;
}
if(buf == NULL && n > 0)
{
setError(ERROR_SENDTO_PARAMS_INVAILD);
return -1;
}
m_send_datahead.check_code = 100;
m_send_datahead.data_total_length = n;
m_send_datahead.data_package_length = 100;
m_send_datahead.MSG = 1;
if( send(m_socket, (char*)&m_send_datahead, sizeof(DataHead),0) == sizeof(DataHead))
{
if(n == 0) //if there is no any packages
return 1;
int package_length = m_send_datahead.data_package_length;
int send_times = n/package_length + 1 ;
int i = 1;
int length_left = n;
while(i <= send_times)
{
if( length_left >= package_length )
{
if(package_length != send(m_socket, buf + (i-1) * package_length ,package_length , 0))
{
setError(ERROR_SEND_FAIL);
return -1;
}
}
else
{
if(length_left != 0)
if(length_left != send(m_socket, buf + (i-1) * package_length ,length_left , 0 ))
{
setError(ERROR_SEND_FAIL);
return -1;
}
}
length_left = n - (i * package_length);
i++;
}
}
else
{
setError(ERROR_SENDHEAD_FAIL);
return -1;
}
return 1;
}
Client::~Client()
{
close(m_socket);
if(m_recvbuf != NULL)
delete m_recvbuf;
}
//connect to server
bool Client::isConnect()
{
if(connect(m_socket,(struct sockaddr*)&m_serveraddr,sizeof(struct sockaddr)) == -1)
{
return false;
}
else
{
return true ;
}
}
谢谢大家!!! |
|