⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 csocket.c

📁 Gambas is a graphical development environment based on a Basic interpreter, like Visual Basic. It us
💻 C
📖 第 1 页 / 共 2 页
字号:
/***************************************************************************  CSocket.c  Network component  (c) 2003-2004 Daniel Campos Fernández <danielcampos@netcourrier.com>  This is the implementation of Socket Gambas Class  This program is free software; you can redistribute it and/or modify  it under the terms of the GNU General Public License as published by  the Free Software Foundation; either version 1, or (at your option)  any later version.  This program is distributed in the hope that it will be useful,  but WITHOUT ANY WARRANTY; without even the implied warranty of  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the  GNU General Public License for more details.  You should have received a copy of the GNU General Public License  along with this program; if not, write to the Free Software  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.***************************************************************************/#define __CSOCKET_C#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <errno.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/ioctl.h>#include <sys/poll.h>#include <sys/un.h>#include <netinet/in.h>#include <arpa/inet.h>#include <unistd.h>#include <netdb.h>#include <time.h>#include "main.h"#include "tools.h"#include "CSocket.h"#include "CServerSocket.h"#include "CDnsClient.h"#define MAX_CLIENT_BUFFER_SIZE 65536#define UNIXPATHMAX 108DECLARE_EVENT (SocketError);DECLARE_EVENT (Closed);DECLARE_EVENT (HostFound);DECLARE_EVENT (Socket_Read);DECLARE_EVENT (Connected);GB_STREAM_DESC SocketStream = {	CSocket_stream_open,	CSocket_stream_close,	CSocket_stream_read,	CSocket_stream_write,	CSocket_stream_seek,	CSocket_stream_tell,	CSocket_stream_flush,	CSocket_stream_eof,	CSocket_stream_lof};/********************************** Routines to call events **********************************/void CSocket_post_error(CSOCKET *mythis){	GB.Raise(mythis,SocketError,0);	GB.Unref((void**)&mythis);}void CSocket_post_closed(CSOCKET *mythis){	GB.Raise(mythis,Closed,0);	GB.Unref((void**)&mythis);}void CSocket_post_hostfound(CSOCKET *mythis){	GB.Raise(mythis,HostFound,0);	GB.Unref((void**)&mythis);}void CSocket_post_connected(CSOCKET *mythis){	GB.Raise(mythis,Connected,0);	GB.Unref((void**)&mythis);}void CSocket_post_data_available(CSOCKET *mythis){	if (mythis->iStatus==7)	GB.Raise(mythis,Socket_Read,0);	GB.Unref((void**)&mythis);}/************************************************** This function is called by DnsClient to inform  that it has finished its work  *************************************************/void CSocket_CallBackFromDns(void *myobj){	int NoBlock=1;	int myval=0;	CSOCKET *mythis;	mythis=(CSOCKET*)myobj;	if ( mythis->iStatus != 5) return;	if ( !mythis->DnsTool->sHostIP)	{		mythis->iStatus=-6; /* error host not found */		dns_close_all(mythis->DnsTool);		GB.Unref((void**)&mythis->DnsTool);		mythis->DnsTool=NULL;		GB.Ref (mythis);		GB.Post (CSocket_post_error,(long)mythis);		if (mythis->OnClose) mythis->OnClose((void*)mythis);		return;	}	GB.FreeString (&mythis->sRemoteHostIP);	GB.NewString ( &mythis->sRemoteHostIP ,mythis->DnsTool->sHostIP,0);	/* Let's turn socket to async mode */	ioctl(mythis->Socket,FIONBIO,&NoBlock);	/* Third, we connect the socket */	mythis->Server.sin_family=AF_INET;  	mythis->Server.sin_port=htons(mythis->iPort);  	mythis->Server.sin_addr.s_addr =inet_addr(mythis->DnsTool->sHostIP);  	bzero(&(mythis->Server.sin_zero),8);	myval=connect(mythis->Socket,(struct sockaddr*)&(mythis->Server), sizeof(struct sockaddr));	if (errno==EINPROGRESS) /* this is the good answer : connect in progress */	{		mythis->iStatus=6;		GB.Watch (mythis->Socket,GB_WATCH_WRITE,(void *)CSocket_CallBackConnecting,(long)mythis);	}	else	{		GB.Watch (mythis->Socket , GB_WATCH_NONE , (void *)CSocket_CallBack,0);		mythis->stream.desc=NULL;		close(mythis->Socket);		mythis->iStatus=0;	}	if (mythis->DnsTool)  	{		dns_close_all(mythis->DnsTool);		GB.Unref((void**)&mythis->DnsTool);		mythis->DnsTool=NULL;  	}	if ( mythis->iStatus<=0 )	{		mythis->iStatus=-3;		GB.Ref (mythis);		GB.Post (CSocket_post_error,(long)mythis);		if (mythis->OnClose) mythis->OnClose((void*)mythis);		return;	}		GB.Ref(mythis);	GB.Post(CSocket_post_hostfound,(long)mythis);}/******************************************************************* This CallBack is used while waiting to finish a connection process ******************************************************************/void CSocket_CallBackConnecting(int t_sock,int type,long lParam){	struct sockaddr_in myhost;	int mylen;	struct timespec mywait;	CSOCKET *mythis;		/*	Just sleeping a little to reduce CPU waste	*/	mywait.tv_sec=0;	mywait.tv_nsec=1000000;	nanosleep(&mywait,NULL);		mythis=(CSOCKET*)lParam;		if (mythis->iStatus!=6) return;	/****************************************************	Checks if Connection was Stablished or there was	an error trying to connect	****************************************************/	mythis->iStatus=CheckConnection(mythis->Socket);	if (mythis->iStatus == 0)	{		GB.Watch (mythis->Socket , GB_WATCH_NONE , (void *)CSocket_CallBack,0);		mythis->stream.desc=NULL;		close(mythis->Socket);		mythis->iStatus=-3;		GB.Ref (mythis);		GB.Post (CSocket_post_error,(long)mythis);		if (mythis->OnClose) mythis->OnClose((void*)mythis);		return;	}	if (mythis->iStatus != 7) return;	// we obtain local IP and host	mylen=sizeof(struct sockaddr);	getsockname (mythis->Socket,(struct sockaddr*)&myhost,&mylen);	mythis->iLocalPort=ntohs(myhost.sin_port);	GB.FreeString( &mythis->sLocalHostIP);	GB.NewString ( &mythis->sLocalHostIP ,inet_ntoa(myhost.sin_addr),0);	GB.Watch (mythis->Socket,GB_WATCH_NONE,(void *)CSocket_CallBack,(long)mythis);	GB.Watch (mythis->Socket,GB_WATCH_WRITE,(void *)CSocket_CallBack,(long)mythis);		mythis->stream.desc=&SocketStream;	mythis->stream._free[0]=(long)mythis;	GB.Ref(mythis);	GB.Post(CSocket_post_connected,(long)mythis);}/******************************************************************* This CallBack is used while socket is connected to remote host ******************************************************************/void CSocket_CallBack(int t_sock,int type,long lParam){	char buf[1];	struct pollfd mypoll;	int numpoll;	struct timespec mywait;	CSOCKET *mythis;		/*	Just sleeping a little to reduce CPU waste	*/	mywait.tv_sec=0;	mywait.tv_nsec=100000;	nanosleep(&mywait,NULL);	/* is there data avilable or an error? */	mythis=(CSOCKET*)lParam;		if (mythis->iStatus!=7) return;		mypoll.fd=t_sock;	mypoll.events=POLLIN | POLLNVAL;	mypoll.revents=0;	numpoll=poll(&mypoll,1,0);	if (numpoll<=0) return;	/* there's data available */	USE_MSG_NOSIGNAL(numpoll=recv(t_sock,(void*)buf,sizeof(char),MSG_PEEK | MSG_NOSIGNAL));	if (!numpoll)	{ /* socket error, no valid data received */		GB.Watch (mythis->Socket , GB_WATCH_NONE , (void *)CSocket_CallBack,0);		mythis->stream.desc=NULL;		close(t_sock);		mythis->iStatus=0;		GB.Ref(mythis);		GB.Post(CSocket_post_closed,(long)mythis);		if (mythis->OnClose) mythis->OnClose((void*)mythis);		return;	}	/******************************************************	There's data available to read, so we'll raise event	Socket_Read	*******************************************************/		GB.Ref(mythis);	GB.Post(CSocket_post_data_available,(long)mythis);	}void CSocket_stream_internal_error(CSOCKET *mythis,int ncode){	/* fatal socket error handling */	GB.Watch (mythis->Socket,GB_WATCH_NONE,(void *)CSocket_CallBack,0);	mythis->stream.desc=NULL;	close(mythis->Socket);	mythis->iStatus = ncode;}////////////////////////////////////////////////////////////////////////////////////################################################################################/*********************************************************************************	"PUBLIC" C/C++ INTERFACE**********************************************************************************///################################################################################///////////////////////////////////////////////////////////////////////////////////* not allowed methods */int CSocket_stream_open(GB_STREAM *stream, const char *path, int mode, void *data){return -1;}int CSocket_stream_seek(GB_STREAM *stream, long pos, int whence){return -1;}int CSocket_stream_tell(GB_STREAM *stream, long *pos){return -1;}int CSocket_stream_flush(GB_STREAM *stream){	return 0; /* OK */}int CSocket_stream_close(GB_STREAM *stream){  CSOCKET *mythis;  if (!(mythis=(CSOCKET*)stream->_free[0]) ) return -1;    if (mythis->DnsTool)  {	dns_close_all(mythis->DnsTool);	GB.Unref((void**)&mythis->DnsTool);	mythis->DnsTool=NULL;  }  if (mythis->iStatus > 0) /* if it's not connected, does nothing */  {	GB.Watch (mythis->Socket , GB_WATCH_NONE , (void *)CSocket_CallBack,0);	stream->desc=NULL;  	close(mythis->Socket);  	mythis->iStatus=0;  }  if (mythis->OnClose) mythis->OnClose((void*)mythis);  return 0;}int CSocket_stream_lof(GB_STREAM *stream, long *len){	CSOCKET *mythis;	int bytes;	*len=0;	if (!(mythis=(CSOCKET*)stream->_free[0]) ) return -1;		if (ioctl(mythis->Socket,FIONREAD,&bytes))	{		CSocket_stream_internal_error(mythis,-4);		if (mythis->OnClose) mythis->OnClose((void*)mythis);		return -1;	}	*len=bytes;	return 0;}int CSocket_stream_eof(GB_STREAM *stream){	CSOCKET *mythis;	int bytes;	if (!(mythis=(CSOCKET*)stream->_free[0]) ) return -1;		if (ioctl(mythis->Socket,FIONREAD,&bytes))	{		CSocket_stream_internal_error(mythis,-4);		if (mythis->OnClose) mythis->OnClose((void*)mythis);		return -1;	}	if (!bytes) return -1;	return 0;}int CSocket_stream_read(GB_STREAM *stream, char *buffer, long len){	CSOCKET *mythis;  	int npos=-1;  	int NoBlock=0;	int bytes;	if (!(mythis=(CSOCKET*)stream->_free[0]) ) return -1;		if (ioctl(mythis->Socket,FIONREAD,&bytes))	{		CSocket_stream_internal_error(mythis,-4);		if (mythis->OnClose) mythis->OnClose((void*)mythis);		return -1;	}	if (bytes < len) return -1;		ioctl(mythis->Socket,FIONBIO,&NoBlock);	USE_MSG_NOSIGNAL(npos=recv(mythis->Socket,(void*)buffer,len*sizeof(char),MSG_NOSIGNAL));	NoBlock++;  	ioctl(mythis->Socket,FIONBIO,&NoBlock);  	if (npos==len) return 0;	if (npos<0)	{		CSocket_stream_internal_error(mythis,-4);		if (mythis->OnClose) mythis->OnClose((void*)mythis);		return -1;	}	if (mythis->OnClose) mythis->OnClose((void*)mythis);	return -1;}int CSocket_stream_write(GB_STREAM *stream, char *buffer, long len){	CSOCKET *mythis;	int npos=-1;	int NoBlock=0;	if (!(mythis=(CSOCKET*)stream->_free[0]) ) return -1;		ioctl(mythis->Socket,FIONBIO,&NoBlock);	USE_MSG_NOSIGNAL(npos=send(mythis->Socket,(void*)buffer,len*sizeof(char),MSG_NOSIGNAL));	NoBlock++;	ioctl(mythis->Socket,FIONBIO,&NoBlock);	if (npos>=0) return 0;	CSocket_stream_internal_error(mythis,-5);	if (mythis->OnClose) mythis->OnClose((void*)mythis);	return -1;}/************************************************************************** To start a UNIX connection **************************************************************************/int CSocket_connect_unix(CSOCKET *mythis,char *sPath,int lenpath){	int NoBlock=1;		if ( mythis->iStatus > 0 ) return 1;	if (!sPath) return 7;	if ( (lenpath<1) || (lenpath>UNIXPATHMAX) ) return 7;	GB.FreeString(&mythis->sRemoteHostIP);  	GB.FreeString(&mythis->sLocalHostIP);	mythis->UServer.sun_family=AF_UNIX;	strcpy(mythis->UServer.sun_path,sPath);  	if ( (mythis->Socket=socket(AF_UNIX,SOCK_STREAM,0))==-1 )  	{    		mythis->iStatus=-2;		GB.Ref (mythis);  		CSocket_post_error(mythis); /* Unable to create socket */		return 2;  	}  	GB.FreeString(&mythis->sPath);	GB.NewString ( &mythis->sPath , mythis->UServer.sun_path ,0);  	mythis->conn_type=1;  	if (connect(mythis->Socket,(struct sockaddr*)&mythis->UServer,sizeof(struct sockaddr_un))==0)  	{		mythis->iStatus=7;		ioctl(mythis->Socket,FIONBIO,&NoBlock);		GB.Watch (mythis->Socket,GB_WATCH_WRITE,(void *)CSocket_CallBack,(long)mythis);		mythis->stream.desc=&SocketStream;		mythis->stream._free[0]=(long)mythis;                // $BM                if (mythis->Host) GB.FreeString(&mythis->Host);                if (mythis->Path) GB.FreeString(&mythis->Path);		                GB.NewString(&mythis->Path,sPath,0);		GB.Ref (mythis);		CSocket_post_connected(mythis);				return 0;  	}	/* Error */	mythis->stream.desc=NULL;	close(mythis->Socket);	GB.FreeString(&mythis->sPath);	mythis->iStatus=-3;		GB.Ref (mythis);	CSocket_post_error(mythis); /* Unable to connect to remote host */		return 3;}/************************************************************************** To start a TCP connection **************************************************************************/int CSocket_connect_socket(CSOCKET *mythis,char *sHost,int lenhost,int myport){	if ( mythis->iStatus > 0 ) return 1;	if (!lenhost) return 9;	if (!sHost)   return 9;	if ( (myport<1) || (myport>65535) ) return 8;   	GB.FreeString(&mythis->sRemoteHostIP);  	GB.FreeString(&mythis->sLocalHostIP);		if ( (mythis->Socket=socket(AF_INET,SOCK_STREAM,0))==-1 )

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -