|
在网络应用开发中,随着需求的改变及性能的提高,程序变得越来越复杂,越来越大。从而导致编译和连接时间长。为更有效地重用代码,应该建立相应的类库。库是包括不同对象的文件。它可作为一个实体进行连接,因而可以极大地提高连接速度。Linux系统可以创建两种库:静态连接库和动态连接库。
为了有效地重用代码,我们采用面向对象地编程方法来实现套接字类库。
由于Linux系统提供的网络API均是C库形式,因此,第一次必须将C形式地系统调用封装到相应地类中,即Wrapper类。在此基础上建立一些公用类。然后,可以根据实际应用的情况,创建一些应用类。另外,还可以创建一些基类用于类的管理或特殊用途。
1 . Wrapper类
根据以上思想,我们建立套接字的Wrapper类,主要包括以下一些类。
MySocket类:封装基础的套接字系统调用,并且实现异常处理。为了满足不同需要,提供了多种形式的函数调用。
MyThread类:封装了POSIX线程的系统调用以实现多线程,并且提供了简单明了的方法来产生线程。
MyMutex类:提供实现互斥锁的基本方法。
MyCondition类:提供实现条件变量的基本方法。
2 . 公用类
公用类主要包括以下类。
TcpServThr类:提供实现基于TCP多线程服务器的方法。
TcpCliThr类:提供实现基于TCP多线程客户的方法。
MessageQue类:提供实现带互斥锁的队列的方法。
3 . 应用类
GameServer类:网络游戏的服务器类,是一个TCP多线程并发服务器。
GameClient类:网络游戏的客户类,是一个基于TCP多线程客户。
另外,还实现了一个基类Thread_interface,用于更灵活地产生线程。
4 . 各类的关系
从图中可以看出,TcpServThr类和TcpCliThr类从MySocket继承而来,可以方便地实现网络操作。它们包括以下两个内部类。
Receiver类:用于产生接收客户数据地线程。
Sender类:用于产生向客户发送数据地线程。
这两个内部类从MyThread继承而来,用于实现多线程。由于这两个内部类仅为了方便地使用TcpServThr类和TcpCliThr类,并不具有普遍意义,因此将它们定义为内部的。在MessageQue类中引用了MyMutex类,以实现互斥锁来保护队列数据的完整性。
可以通过引用关系或继承关系生成新的类,例如继承MySocket类以生成多进程并发服务器。也可以对已有的类进行修改从而增加新的功能,使其更加完善。由此看出,建立套接字类库能迅速地产生新的应用,也能方便地对原系统进行升级,程序也具有良好的结构,便于阅读和调试,从而极大地提高开发效率。
![](http://www.linuxfans.org/nuke/modules/Forums/files/1_539.png)
套接字系统调用:MySocket类
MySocket类是该套接字类库的核心,它封装了与套接字相关的主要系统调用。其类声明源代码见如下:
[code:1]
/*File : mysocket.h*/
#include <unistd.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/time.h>
/*Define constant*/
const unsigned MysBUF_SIZE=1024; //固定字串缓冲区长度
const unsigned MysMAX_NAME_LEN=256; //最大名字长度
const unsigned MysRX_BUF_SIZE=4096; //默认接收缓冲区大小
const unsigned MysTX_BUF_SIZE=4096; //默认发送缓冲区大小
const unsigned MAXCONN=5; //默认最大连接数
const unsigned MysSOCKET_DEFAULT_PORT=1234; //默认端口号
/*Define Error*/
enum MySocketError{ //定义枚举类型MySocketError,包括所有自定义错误码
MySOCKET_NO_ERROR=0,
MySOCKET_INVALID_ERROR_CODE,
//socket error codes
MySOCKET_ADDEPT_ERROR,
MySOCKET_BIND_ERROR,
MySOCKET_BUFOVER_ERROR,
MySOCKET_CONNECT_ERROR,
MySOCKET_FILESYSTEM_ERROR,
MySOCKET_GETOPTION_ERROR,
MySOCKET_HOSTNAME_ERROR,
MySOCKET_INIT_ERROR,
MySOCKET_LISTEN_ERROR,
MySOCKET_PEERNAME_ERROR,
MySOCKET_PROTOCOL_ERROR,
MySOCKET_RECEIVE_ERROR,
MySOCKET_REQUEST_TIMEOUT,
MySOCKET_SERVICE_ERROR,
MySOCKET_SETOPTOPN_ERROR,
MySOCKET_SOCKNAME_ERROR,
MySOCKET_SOCKETTYPE_ERROR,
MySOCKET_TRANSMIT_ERROR,
};
/*****************************************************
Class name:MySocket
Function:A wrapper class of basoc socket function.
*****************************************************/
class MySocket //定义MySocket类,其成员函数包括以下几类
{
protected:
sa_family_t address_family;
int protocol_family;
int socket_type;
int port_number;
int Mysocket;
int conn_socket;
MySocketError socket_error;
protected:
int bytes_read;
int bytes_moved;
int is_connected;
int is_bound;
public:
sockaddr_in sin;
sockaddr_in remote_sin;
public:
MySocket();
MySocket(int st,int port,char *hostname=0);
MySocket(sa_family_t af,int st,int pf,int port,char* hostname=0);
virtual ~MySocket();
public:
void SetAddressFamily(sa_family_t af) {address_family=af;}
void SetProtocolFamily(int pf) {protocol_family=pf;}
int GetProtocolFamily(){return protocol_family;}
void SetSocketType(int st){socket_type=st;}
int GetSocketType(){return socket_type;}
void SetPortNumber(int p){port_number=p;}
int GetBoundSocket(){return Mysocket;}
int GetSocket(){return Mysocket;}
int GetRemoteSocket{return conn_socket;}
public://Socket fuction
int Socket();
int InitSocket(int st,int port,char *hostname=0);
int InitSocket(sa_family_t af, int st, int pf, int port ,char* hostname=0);
void Close();
void Close(int &s);
void CloseSocket();
void CloseRemoteSocket();
int Bind();
int Connect();
int Accept();
int Listen(int mac_connections=MAXCONN);
void ShutDown(int how=0);
void ShutDown(int &s,int how=0);
void ShutDownSocket(int how=0);
void ShutCownRemoteSocket(int how=0);
int GetSockOpt(int s, int level, int optName, void *optVal, unsigned *optLen);
int GetSockOpt(int level, int optName, void *optVal, unsigned *optLen);
int SetSockOpt(int s, int level, int optName,const void *optVal, unsigned optLen);
int SetSockOpt(int level, int optName,const void *optVal, unsigned optLen);
//Stream function
int Recv(void *buf, int bytes, int flags=0);//just for client
int Recv(int s, void *buf, int bytes, int flags=0);
int Recv(void *buf, int bytes,int seconds,int useconds,int flags=0);//just for client
int Recv(int s,void *buf, int bytes,int seconds,int useconds,int flags=0);
int Send(const void *buf, int bytes, int flags=0);//just for client
int Send(int s,const void *buf, int bytes, int flags=0);
int RemoteRecv(void *buf,int bytes,int seconds,int useconds, int flags=0);//just for client
int RemoteRecv(void *buf,int bytes,int flags=0);//just for server
int RemoteRecv(const void *buf,int bytes,int flags=0);
void ResetRead(){bytes_read=0;}
void ResetWrite(){bytes_moved=0;}
//information database
int GetPeerName(int s, sockaddr_in *sa);
int GetPeerName();
int GetSockName(int s, sockaddr_in *sa);
int GetSockName();
int GetServByName(char *name,char *protocol=0);
int GetServByName(int port, char *protocol=0);
servent *GetServiceInformation(char *name,char *protocol=0);
servent *GetServiceInformation(int port, char *protocol=0);
int GetPortNumber();
int GetHostName(char *sbuf);
int GetIPAddress(char *sbuf);
int GetDomainName(char *sbuf);
int GetBoundIPAddress(char *sbuf);
int GetRemoteHostName(char *sbuf);
hostent *GetHostInformation(char *hostname);
void GetClientInfo(char *client_name,int &r_port);
sa_family_t GetAddressFamily();
sa_family_t GetRemoteAddressFamily();
//Process control functions
int ReadSelect(int s, int seconds, int useconds);
int BytesRead(){return bytes_read;}
int BytesMoved(){return bytes_moved;}
int SetBytesRead(int bytes=0){return bytes_read=bytes;}
int SetBytesMoved(int bytes=0){return bytes_moves=bytes;}
int *GetBytesRead(){return &bytes_read;}
int *GetBytesMoved(){return &bytes_moved;}
int IsConnected(){return is_connected==-1;}
int IsBound(){return is_bound==1;}
int SetSocket(int s){return Mysocket=s;}
int SetRemoteSocket(int s){return conn_socket=s;}
void ReleaseSocket(){Mysocket=(int)-1;}
void ReleaseRemoteSocket(){conn_socket=(int)-1;}
//Datagram fuctions
int RecvFrom(int s,sockaddr_in *sa, void *buf,int bytes,int seconds,int useconds,int flags=0);
int RecvFrom(int s,sockaddr_in *sa, void *buf,int bytes,int flags=0);
int SendTo(int s, sockaddr_in *sa, void *buf);
int RecvFrom(void *buf, int bytes, int flags=0);
int RecvFrom(void *buf, int bytes, int seconds, int useconds, int flags=0);
int SendTo(void *buf, int bytes, int flages);
//Exception handling functions
MySocketError GetSocketError(){return socket_error;}
MySocketError GetSocketError() const {return socket_error;}
MySocketError SetSocketError(MySocketError err){
return socket_error=err;
}
MysocketError ResetSocketError(){
return socket_error=MySOCKET_NO_ERROR;
}
MysocketError ResetError(){
return socket_error=MySOCKET_NO_ERROR;
}
};
[/code:1]
1. MySocket类的成员变量
在一个类中,成员函数代表了该类的特性及状态。MySocket类的成员变量存放与套接字相关的信息,其内容如下:
address_family:存放地址簇,如AF_INET。
protocol_family:存放协议簇,如IPPROTO_TCP。
socket_type:套接字类型,如SOCK_STREAM、SOCK_DGRAM。
port_number:端口号。
Mysocket:套接字的描述符。对于SOCK_STREAM类型的套接字为侦听套接字描述符。
conn_socket:连接套接字描述符。对于SOCK_DGRAM类型的套接字无效。
socket_error:自定义的套接字错误码。
bytes_read:读入的字节数。
bytes_move:写出的字节数。
is_connected:是否已连接。0为未连接,否则已连接。
is_bound:套接字是否已绑定。
sin:本地套接字地址。
remote_sin:远程套接字地址。
2. MySocket类实现的功能
MySocket类所实现的功能分为以下几类。
参数设置。用于设置与套接字相关的参数,如SetAddressFamily()、SetProtocolFamily()、SetPortNumber()等。
套接字功能。用于初始化/关闭套接字,以及绑定连接等操作,如InitSocket()、Close()、Bind()、Connect()、Accept()、Listen()、ShutDown()等。
基于流的I/O功能。用于TCP的读写操作,如Recv()、Send()、RemoteRecv()、RemoteSend()等。
套接字信息数据库功能。用于获取与套接字相关的参数,如GetPeerName()、GetSockName()、GetIPAddress()等。
套接字状态功能。用于获得当前套接字状态,如IsConnedted()、IsBound()、SetSocket()等。
基于数据报I/O功能。用于UDP的读写操作,如RecvFrom()、SendTo()等。
异常处理功能。用于获取或设置错误码,如GetSocketError()、SetSocketError()等。
3. 利用OOP的重载功能
为了适应不同的用途,同一系统调用被封装到不同的成员函数中,这些函数使用同一名称却又不同的参数列表,这是利用OOP的重载实现的。例如,基于TCP的读功能有四个成员函数:
int Recv(void *buf,int bytes,int flags=0):只有当MySocket类为客户所使用时,才调用该函数。它从MySocket套接字中读数据。
int Recv(void *buf,int bytesmint seconds,int useconds,int flags=0):与上一函数一样,但增加了超时处理功能。
int Recv(int s,void *buf,int bytes,int flags=0):从一指定的套接字中读数据。
int Recv(int s,void *buf,int bytesmint seconds,int useconds,int flags=0):与上一函数一样,但增加了超时处理功能。 |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?注册
×
|