Скачиваний:
17
Добавлен:
01.05.2014
Размер:
6.86 Кб
Скачать
#ifndef SOCK_H
#define SOCK_H

#include <iostream.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <memory.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/systeminfo.h>

const int BACKLOG_NUM = 5;

class sock {
     private:
    	int sid;     	// socket descriptor
        int domain; 	// socket domain
        int socktype;   // socket type
        int rc;      	// member function return status code

	/* Build a socket name based on the given hostname and port number */
	int constr_name( struct sockaddr_in& addr, const char* hostnm, int port )
        {
            addr.sin_family = domain;
            if (!hostnm) 
           	addr.sin_addr.s_addr = INADDR_ANY;
            else {
            	struct hostent *hp = gethostbyname(hostnm);
            	//if (hp==0) {
                //	perror("gethostbyname"); return -1;
            	//}
              	memcpy((char*)&addr.sin_addr,(char*)hp->h_addr, hp->h_length);
           }
           addr.sin_port = htons(port);
           return sizeof(addr);
        };
        /* Build a socket name based on the given pathname */
	int constr_name( struct sockaddr& addr, const char* Pathnm ) 
        {
           addr.sa_family = domain;
           strcpy(addr.sa_data, Pathnm );
           return sizeof(addr.sa_family) + strlen(Pathnm) + 1;
        };

        /* Convert an IP address to a host name */
        char* ip2name( const struct in_addr in )
        {
           u_long laddr;
           if ((int)(laddr = inet_addr(inet_ntoa(in))) == -1) return 0;
           struct hostent *hp = gethostbyaddr((char *)&laddr, sizeof (laddr), AF_INET);
           if (hp == NULL) return 0;
           for (char **p = hp->h_addr_list; *p != 0; p++) {
                (void) memcpy((char*)&in.s_addr, *p, sizeof (in.s_addr));
                if (hp->h_name) return hp->h_name;
           }
           return 0;
        };
     public:
     	sock( int dom, int type, int protocol=0 ) : domain(dom), socktype(type)
        {
           if ((sid=socket(domain=dom, socktype=type,protocol))<0)
              perror("socket");
     	};
        ~sock()  { shutdown(); close(sid);  };			// destructor
	int fd()	{ return sid; };	// return the socket file descriptor
        int good()    { return sid >= 0;  };			// check sock object status
	int bind( const char* name, int port=-1 ) {		// assign a UNIX name
           if (port == -1) { // UNIX  domain socket
          	 struct sockaddr addr;
         	 int len = constr_name( addr, name);
            	 if ((rc= ::bind(sid,&addr,len))<0) perror("bind"); 
           } else {
		 struct sockaddr_in addr;
         	 int len = constr_name( addr, name, port);
            	 if ((rc= ::bind(sid, (struct sockaddr *)&addr, len))<0  ||
                     (rc=getsockname(sid, (struct sockaddr*)&addr, &len))<0)
                    perror("bind or getsockname");
                 else cerr << "Socket port: " << ntohs(addr.sin_port) << endl;
           }
           if (rc!=-1 && socktype!=SOCK_DGRAM && (rc=listen(sid,BACKLOG_NUM)) < 0) 
          	perror("listen");
	   return rc;
        };
        int accept ( char* name, int* port_p)
        {
           if (!name) return ::accept(sid, 0, 0);
           if (!port_p || *port_p == -1) { // UNIX domain socket
               struct sockaddr addr;
               int size = sizeof(addr);
               if ((rc = ::accept(sid, &addr, &size)) >-1)
	          strncpy(name,addr.sa_data,size), name[size]='\0';
            } else {
	       struct sockaddr_in addr;
	       int size = sizeof (addr);
               if ((rc = ::accept( sid, (struct sockaddr*)&addr, &size)) >-1)
               {
	  	  if (name) strcpy(name,ip2name(addr.sin_addr));
		  if (port_p) *port_p = ntohs(addr.sin_port);
               }
            }
            return rc;
        };
       	int connect( const char* hostnm, int port=-1 ) 		// connect to a UNIX socket
        {
           if (port==-1) { // UNIX domain socket
              struct sockaddr addr;
              int len = constr_name( addr, hostnm);
              if ((rc= ::connect(sid,&addr,len))<0) perror("bind"); 
       	   } else {
              struct sockaddr_in addr;
              int len = constr_name( addr, hostnm, port);
              if ((rc= ::connect(sid,(struct sockaddr *)&addr,len))<0) perror("bind");
           }
           return rc;
        };
        int write( const char* buf, int len, int flag=0, int nsid=-1 ) 	// write a msg
        {
            return ::send(nsid==-1 ? sid : nsid, buf, len, flag );
        };	
        int read( char* buf, int len, int flag=0, int nsid=-1 ) 	// read a msg
        {
            return ::recv(nsid==-1 ? sid : nsid, buf, len, flag );
       	};
	/* write to a UNIX socket of the given socket name */
       	int writeto( const char* buf, int len, int flag, const char* name, const int port, int nsid=-1 )
       	{
            if (port==-1) { 
        	struct sockaddr addr;
                int size = constr_name( addr, name);
                return ::sendto(nsid==-1 ? sid : nsid, buf, len, flag, &addr, size );
            } else {
            	struct sockaddr_in addr;
                char buf1[80];
                if (!name) { // use local host if not specified
                   if (sysinfo(SI_HOSTNAME,buf1,sizeof buf1)==-1L) perror("sysinfo");
                   name = buf1;
                }
                int size = constr_name( addr, name, port);
                return ::sendto(nsid==-1 ? sid : nsid, buf, len, flag, 
	                  (struct sockaddr*)&addr, size );
            }
	};
	/* receieve a message from a UNIX domain socket */
        int readfrom( char* buf, int len, int flag, char* name, int *port_p, int nsid =-1)
       	{
            if (!port_p || *port_p == -1) { // UNIX domain socket
               struct sockaddr addr;
               int size = sizeof(addr);
               if ((rc=::recvfrom(nsid==-1 ? sid : nsid, buf, len, flag, &addr, &size)) >-1
                        && name)
                  strncpy(name,addr.sa_data,rc), name[rc]='\0';
            } else {
	      struct sockaddr_in addr;
	      int size = sizeof (addr);
              if ((rc = ::recvfrom(nsid==-1 ? sid : nsid, buf, len, flag, 
					(struct sockaddr*)&addr, &size)) >-1)
              {
		if (name) strcpy(name,ip2name(addr.sin_addr));
		if (port_p) *port_p = ntohs(addr.sin_port);
              }
           }
           return rc;
	};
       	int shutdown( int mode = 2 ) 	// shutdown a socket
        {
      	      return ::shutdown (sid,mode);
       	};
}; 		/* class sock */

#endif
Соседние файлы в папке socket