| 
 | 
 
在网络应用开发中,随着需求的改变及性能的提高,程序变得越来越复杂,越来越大。从而导致编译和连接时间长。为更有效地重用代码,应该建立相应的类库。库是包括不同对象的文件。它可作为一个实体进行连接,因而可以极大地提高连接速度。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类以生成多进程并发服务器。也可以对已有的类进行修改从而增加新的功能,使其更加完善。由此看出,建立套接字类库能迅速地产生新的应用,也能方便地对原系统进行升级,程序也具有良好的结构,便于阅读和调试,从而极大地提高开发效率。 
 
  
 
 
 
套接字系统调用: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):与上一函数一样,但增加了超时处理功能。 |   
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?注册  
 
×
 
 
 
 
 |