sockets.c
上传用户:seven77cht
上传日期:2007-01-04
资源大小:486k
文件大小:8k
- /***************************************
- $Header: /home/amb/wwwoffle/RCS/sockets.c 2.9 1999/07/05 18:46:16 amb Exp $
- WWWOFFLE - World Wide Web Offline Explorer - Version 2.5.
- Socket manipulation routines.
- ******************/ /******************
- Written by Andrew M. Bishop
- This file Copyright 1996,97,98,99 Andrew M. Bishop
- It may be distributed under the GNU Public License, version 2, or
- any higher version. See section COPYING of the GNU Public license
- for conditions under which this file may be redistributed.
- ***************************************/
- #include <stdio.h>
- #include <string.h>
- #include <errno.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <sys/time.h>
- #include <netdb.h>
- #include <sys/param.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include "errors.h"
- #include "sockets.h"
- /*++++++++++++++++++++++++++++++++++++++
- Opens a socket for a client.
- int OpenClientSocket Returns the socket file descriptor.
- char* host The name of the remote host.
- int port The socket number.
- int timeout The time to wait for the socket to connect.
- ++++++++++++++++++++++++++++++++++++++*/
- int OpenClientSocket(char* host, int port,int timeout)
- {
- int s;
- int retval;
- struct sockaddr_in server;
- struct hostent* hp;
- int noblock,flags;
- server.sin_family=AF_INET;
- server.sin_port=htons((unsigned short)port);
- hp=gethostbyname(host);
- if(!hp)
- {
- unsigned long int addr=inet_addr(host);
- if(addr!=-1)
- hp=gethostbyaddr((char*)addr,sizeof(addr),AF_INET);
- if(!hp)
- {errno=-1;PrintMessage(Warning,"Unknown host '%s' for server [%!s].",host);return(-1);}
- }
- memcpy((char*)&server.sin_addr,(char*)hp->h_addr,sizeof(server.sin_addr));
- s=socket(PF_INET,SOCK_STREAM,0);
- if(s==-1)
- {PrintMessage(Warning,"Cannot create client socket [%!s].");return(-1);}
- #ifdef O_NONBLOCK
- flags=fcntl(s,F_GETFL,0);
- if(flags!=-1)
- noblock=fcntl(s,F_SETFL,flags|O_NONBLOCK);
- else
- noblock=-1;
- #else
- flags=1;
- noblock=ioctl(s,FIONBIO,&flags);
- #endif
- retval=connect(s,(struct sockaddr *)&server,sizeof(server));
- if(retval==-1 && noblock!=-1 && errno==EINPROGRESS)
- {
- fd_set writefd;
- struct timeval tv;
- FD_ZERO(&writefd);
- FD_SET(s,&writefd);
- tv.tv_sec=timeout;
- tv.tv_usec=0;
- retval=select(s+1,NULL,&writefd,NULL,&tv);
- if(retval>0)
- {
- int arglen=sizeof(int);
- if(getsockopt(s,SOL_SOCKET,SO_ERROR,&retval,&arglen)<0)
- retval=errno;
- if(retval!=0)
- errno=retval,retval=-1;
- if(errno==EINPROGRESS)
- errno=ETIMEDOUT;
- }
- else if(retval==0)
- errno=ETIMEDOUT,retval=-1;
- }
- if(retval<0)
- {
- close(s);
- s=-1;
- PrintMessage(Warning,"Connect fail [%!s].");
- }
- else
- {
- #ifdef O_NONBLOCK
- flags=fcntl(s,F_GETFL,0);
- if(flags!=-1)
- fcntl(s,F_SETFL,flags&~O_NONBLOCK);
- #else
- flags=0;
- ioctl(s,FIONBIO,&flags);
- #endif
- }
- return(s);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Opens a socket for a server.
- int OpenServerSocket Returns a socket to be a server.
- int port The port number to use.
- ++++++++++++++++++++++++++++++++++++++*/
- int OpenServerSocket(int port)
- {
- int s;
- int retval;
- struct sockaddr_in server;
- int reuse_addr=1;
- s=socket(PF_INET,SOCK_STREAM,0);
- if(s==-1)
- {PrintMessage(Warning,"Cannot create server socket [%!s].");return(-1);}
- setsockopt(s,SOL_SOCKET,SO_REUSEADDR,&reuse_addr,sizeof(reuse_addr));
- server.sin_family=AF_INET;
- server.sin_addr.s_addr=INADDR_ANY;
- server.sin_port=htons((unsigned int)port);
- retval=bind(s,(struct sockaddr*)&server,sizeof(server));
- if(retval==-1)
- {PrintMessage(Warning,"Failed to bind server socket [%!s].");return(-1);}
- listen(s,4);
- return(s);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Waits for a connection on the socket.
- int AcceptConnect returns a socket with a remote connection on the end.
- int socket Specifies the socket to check for.
- ++++++++++++++++++++++++++++++++++++++*/
- int AcceptConnect(int socket)
- {
- int s;
- s=accept(socket,(struct sockaddr*)0,(int*)0);
- if(s==-1)
- PrintMessage(Warning,"Accept on server socket failed [%!s].");
- return(s);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Determines the hostname and port number used for a socket on the other end.
- int SocketRemoteName Returns 0 on success and -1 on failure.
- int socket Specifies the socket to check.
- char **name Returns the hostname.
- char **ipname Returns the hostname as an IP address.
- int *port Returns the port number.
- ++++++++++++++++++++++++++++++++++++++*/
- int SocketRemoteName(int socket,char **name,char **ipname,int *port)
- {
- struct sockaddr_in server;
- int length=sizeof(server),retval;
- static char host[MAXHOSTNAMELEN],ip[16];
- struct hostent* hp=NULL;
- retval=getpeername(socket,(struct sockaddr*)&server,&length);
- if(retval==-1)
- PrintMessage(Warning,"Failed to get socket peername [%!s].");
- else
- {
- hp=gethostbyaddr((char*)&server.sin_addr,sizeof(server.sin_addr),AF_INET);
- if(hp)
- strcpy(host,hp->h_name);
- else
- strcpy(host,inet_ntoa(server.sin_addr));
- strcpy(ip,inet_ntoa(server.sin_addr));
- if(name)
- *name=host;
- #ifdef __CYGWIN__
- if(!strcmp(ip,"127.0.0.1"))
- *name="localhost";
- #endif
- if(ipname)
- *ipname=ip;
- if(port)
- *port=ntohs(server.sin_port);
- }
- return(retval);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Determines the hostname and port number used for a socket on this end.
- int SocketLocalName Returns 0 on success and -1 on failure.
- int socket Specifies the socket to check.
- char **name Returns the hostname.
- char **ipname Returns the hostname as an IP address.
- int *port Returns the port number.
- ++++++++++++++++++++++++++++++++++++++*/
- int SocketLocalName(int socket,char **name,char **ipname,int *port)
- {
- struct sockaddr_in server;
- int length=sizeof(server),retval;
- static char host[MAXHOSTNAMELEN],ip[16];
- struct hostent* hp=NULL;
- retval=getsockname(socket,(struct sockaddr*)&server,&length);
- if(retval==-1)
- PrintMessage(Warning,"Failed to get socket name [%!s].");
- else
- {
- hp=gethostbyaddr((char*)&server.sin_addr,sizeof(server.sin_addr),AF_INET);
- if(hp)
- strcpy(host,hp->h_name);
- else
- strcpy(host,inet_ntoa(server.sin_addr));
- strcpy(ip,inet_ntoa(server.sin_addr));
- if(name)
- *name=host;
- #ifdef __CYGWIN__
- if(!strcmp(ip,"127.0.0.1"))
- *name="localhost";
- #endif
- if(ipname)
- *ipname=ip;
- if(port)
- *port=ntohs(server.sin_port);
- }
- return(retval);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Closes a previously opened socket.
- int CloseSocket Returns 0 on success, -1 on error.
- int socket The socket to close
- ++++++++++++++++++++++++++++++++++++++*/
- int CloseSocket(int socket)
- {
- int retval=close(socket);
- if(retval==-1)
- PrintMessage(Warning,"Socket close failed [%!s].");
- return(retval);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Get the Fully Qualified Domain Name for the local host.
- char *GetFQDN Return the FQDN.
- ++++++++++++++++++++++++++++++++++++++*/
- char *GetFQDN(void)
- {
- static char fqdn[256],**h;
- struct hostent* hp;
- int type=hp->h_addrtype;
- int length=hp->h_length;
- char addr[sizeof(struct in_addr)];
- /* Try gethostname(). */
- if(gethostname(fqdn,255)==-1)
- {PrintMessage(Warning,"Failed to get hostname [%!s].");return(NULL);}
- if(strchr(fqdn,'.'))
- return(fqdn);
- /* Try gethostbyname(). */
- hp=gethostbyname(fqdn);
- if(!hp)
- {errno=-1;PrintMessage(Warning,"Can't get IP address for host [%!s].");return(NULL);}
- if(strchr(hp->h_name,'.'))
- {
- strcpy(fqdn,hp->h_name);
- return(fqdn);
- }
- for(h=hp->h_aliases;*h;h++)
- if(strchr(*h,'.'))
- {
- strcpy(fqdn,*h);
- return(fqdn);
- }
- /* Try gethostbyaddr(). */
- type=hp->h_addrtype;
- length=hp->h_length;
- memcpy(addr,(char*)hp->h_addr,sizeof(struct in_addr));
- hp=gethostbyaddr(addr,length,type);
- if(!hp)
- {errno=-1;PrintMessage(Warning,"Can't get hostname for IP address [%!s].");return(NULL);}
- if(strchr(hp->h_name,'.'))
- {
- strcpy(fqdn,hp->h_name);
- return(fqdn);
- }
- for(h=hp->h_aliases;*h;h++)
- if(strchr(*h,'.'))
- {
- strcpy(fqdn,*h);
- return(fqdn);
- }
- strcpy(fqdn,hp->h_name);
- return(fqdn);
- }