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

📄 tcp_socket.c

📁 unix下多进程编程实例
💻 C
字号:
/********************************************************************
 * NAME         : TCP_socket.c
 * FUNCTION     : socket communication (unix) library
 * AUTHOR		: ZZ_NODE/2000.12.15/songqufei
 * OS           : solaris
 ********************************************************************/

/********************************************************************
 *    INCLUDE FILES
 ********************************************************************/
#include "TCP_socket.h"

/********************************************************************
 * NAME     : TCP_ListenForConnection
 * FUNCTION : create server and listen for connection
 * PROCESS  : 1. get service by name
 *          : 2. create socket
 *          : 3. bind to local address
 *          : 4. listen for connect
 * INPUT    : szServiceName : service name
 * OUTPUT   : 
 * UPDATE   :
 * RETURN   : -1    : fail
 *          : other : socket ID
 * AUTHOR	: ZZ-NODE/2000.12.15/songqufei
 * CALL     : getservbyname()
 *          : socket()
 *          : bind()
 *          : listen()
 ********************************************************************/
int TCP_ListenForConnection( char *szServiceName )
{
    struct servent *pstServEnt;
    struct sockaddr_in sin;
    int		sd;        /* socket descript */
	int		sockreuse = 1,sockkeepalive = 1;

    /* -----<get service by name>----- */
    if( (pstServEnt = getservbyport(htons(atoi(szServiceName)), "tcp" ))==NULL) {
		if( (pstServEnt = getservbyname( szServiceName, "tcp" ))==NULL) {
			DebugLog("getservbyname error");
			return( -1 );
		}
    }

    /* -----<creat socket>----- */
    sd = socket(AF_INET, SOCK_STREAM, 0 );
    if ( sd < 0) {
        DebugLog("socket error");
        return ( -1 );
    }

    /* -----<bind to local address>----- */
    memset((char *) &sin,0,sizeof(struct sockaddr_in));
    sin.sin_family = AF_INET;
    sin.sin_addr.s_addr = htonl(INADDR_ANY);
    sin.sin_port = pstServEnt -> s_port;

    setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &sockreuse, sizeof(sockreuse));
    setsockopt(sd, SOL_SOCKET, SO_KEEPALIVE, &sockkeepalive, sizeof(sockkeepalive));

    if ( bind( sd, (char *)&sin, sizeof(sin) ) < 0 ) {
        DebugLog("bind error");
        close( sd );
        return ( -1 );
    }

    /* -----<listen for connection>----- */
    if(listen( sd, LISTENQUEUE )<0) {
		DebugLog("listen error");
		close(sd);
		return -1;
	};

    return ( sd );
}


/********************************************************************
 * NAME     : TCP_DoAccept
 * FUNCTION : server accept connection from client
 * PROCESS  : 1. set blocking mode
 *          : 2. waiting for connect
 * INPUT    : sd : socket ID 
 * OUTPUT   : 
 * UPDATE   :
 * RETURN   : new socket ID 
 * AUTHOR	: ZZ-node/2000.12.15/songqufei
 * CALL     : accept()
 ********************************************************************/
int TCP_DoAccept(int sd )
{
    int    newsd;
    struct sockaddr_in from;
    int    len;

    len = sizeof( from );
    memset( &from, 0, len );
    newsd = accept( sd, &from, &len );

    if( newsd < 0 ) {
		DebugLog("Accept failed" );
		return -1;
    }

    return( newsd );
}


/********************************************************************
 * NAME 		: TCP_SendPacket() 
 * FUNCTION		: send packet 
 * PROCESS		: 1.send packet 
 * INPUT		: sd       :socket descriptor
 *				: pPacket  :pointer to packet 
 * OUTPUT		: 
 * UPDATE		:
 * RETURN		: -1      : error
 *				: >0	  : size of data send out
 * AUTHOR		: ZZ-NODE/2000.12.15/songqufei
 * CALL			: Send_Packet()
 ********************************************************************/
int TCP_SendPacket(int sd,char *pPacket )
{
	PacketHead *pPackHead;
 	int lLong,lSendSize;
	int pktid,retid;

	pPackHead = (PacketHead *)pPacket;
	
	pPackHead->iMsgCode = 0;
	strcpy(pPackHead->sSystemID,SYSTEM_ID);
	
	DebugLog("Begin send packet...");

	lLong = pPackHead->lPacketSize;

	if(lLong<=0) {
		DebugLog("Packet Size Is Error!\n");
		return -1;
	}

	pktid = pPackHead->iPacketID;
	retid = pPackHead->iRetPktID;
	
	lSendSize = Send_Packet( sd, pPacket, lLong ); 

	if(lLong != lSendSize) {
		DebugLog("Return Packet id:%d error\n",pktid);
		return -1;
	}
	DebugLog("=== Send %d,PKTID:%d RETID: %d size: %d ===",sd,pktid,retid,lSendSize);

	return ( lLong );
}


/********************************************************************
 * NAME     : Send_Packet
 * FUNCTION : send data using socket
 * PROCESS  : 1. split data into many packet
 *          : 2. send packets by loop 
 * INPUT    : sd      : socket ID
 *          : pBuffer : pointer of data buffer
 *          : lSize   : buffer size
 * OUTPUT   : 
 * UPDATE   :
 * RETURN   : -1    : send fail
 *          : other : bytes send
 * AUTHOR	: ZZ-NODE/2000.12.15/songqufei
 * CALL     : send()
 ********************************************************************/
int Send_Packet(int sd,char *pBuffer,int lSize )
{
	int	iEachMaxSiz = 4096;		/* each received max size  */
	int	iEachRealSiz = 0;		/* each need receive  size  */
    int iTotalSend = 0;			/* the total received bytes */
	int	iLeftSiz;				/* the left size */
    int	iSele,iSend,iRetry=0;	/* select return value, the received real size, retry time */ 
    fd_set  wr_set;
    struct timeval  tv;

    tv.tv_sec = 1;
    tv.tv_usec = 0;

	iLeftSiz = lSize;
	while(1){
		if(iLeftSiz<=0)	break;	/* 已经全部发完 */

		FD_ZERO(&wr_set);
		FD_SET(sd, &wr_set);
		iSele = (int) select(sd+1, NULL, &wr_set, NULL, &tv);
		if(iSele < 0 || iRetry >= 60) {
			DebugLog("发送数据包select出错。");
			ErrorLog(COMMERR_TYPE,"SYSTEM","发送数据包select出错。");
			return( -1 );         
		}else if(iSele == 0 && iRetry++<60){
			continue;
		}
		
		iEachRealSiz = iLeftSiz>iEachMaxSiz? iEachMaxSiz: iLeftSiz;
		iSend = send(sd,pBuffer,iEachRealSiz,0);
		if(iSend < 0) {
			DebugLog("发送数据包send出错。");
			ErrorLog(COMMERR_TYPE,"SYSTEM","发送数据包send出错。");
			return( -1 );         
		}

		pBuffer += iSend;		/* 修改buf指针 */
		iLeftSiz -= iSend;		/* 重新计算剩余字节数 */
		iTotalSend += iSend;	/* 计算发送字节总数 */
	}

    return ( iTotalSend );
}


/********************************************************************
 * NAME 		: TCP_RecvPacket() 
 * FUNCTION		: recieve packet and return all information
 * PROCESS		: 1.check recieve buffer of socket to find error
 *				: 2.malloc memory for packet
 *				: 3.receive packet
 * INPUT		: sd      : socket descriptor
 *				: nTimeOut: time out value ( second ) 
 * OUTPUT		: erflag  : error flag set when socket is disconnect
 * UPDATE		:
 * RETURN		: NULL    : error
 *				: other   : pointer to packet head
 * AUTHOR		: ZZ-NODE/2000.12.18/songqufei 
 * CALL			: Recv_Packet()
 ********************************************************************/
char *TCP_RecvPacket(int sd,int nTimeOut,int *errflag )
{
	PacketHead *pPackHead;
	char       *pPacket;

	if(errflag!=NULL) {
		*errflag = 0;
	};

	pPacket = Recv_Packet(sd,nTimeOut,errflag);
    if((errflag!=NULL && *errflag) || !pPacket) {
		DebugLog("=== RECEIVE PACKET FROM sd:%d ERROR ===",sd);
        return NULL;
    }

	pPackHead = (PacketHead *)pPacket;
	DebugLog("=== Recv %d,PKTID:%d RETID:%d PKTLEN:%d ===",sd,pPackHead->iPacketID,
		pPackHead->iRetPktID,pPackHead->lPacketSize);

    return( pPacket );
}


/********************************************************************
 * NAME 		: Recv_Packet() 
 * FUNCTION		: recieve packet and return all information
 * PROCESS		: 1.check recieve buffer of socket to find error
 *				: 2.malloc memory for packet
 *				: 3.receive packet
 * INPUT		: sd      : socket descriptor
 *				: nTimeOut: time out value ( second ) 
 * OUTPUT		: erflag  : error flag set when socket is disconnect
 * UPDATE		:
 * RETURN		: NULL    : error
 *				: other   : pointer to packet head
 * AUTHOR		: ZZ-NODE/2000.12.18/songqufei 
 * CALL			: TCEU_CheckRecvBuffer()
 *				: TCEU_TCPRecv()
 ********************************************************************/
static char *Recv_Packet(int sd,int nTimeOut,int *errflag )
{
	char	*pPacket;
	int		lLong,lRealSize;
	PacketHead	stHead;

	TCcom_InitErrorMsg();

	if(errflag!=NULL) {
		*errflag = 0;
	}

	/* 检查应收取数据包的长度 */
	lLong = TCEU_CheckRecvBuffer( sd, nTimeOut );

	if(lLong <= 0){
		DebugLog("packet size less than or equal 0");
		goto _err;
	}

	DebugLog("%s:receive size = %d",szSubSystemID,lLong);

	pPacket = (char *)malloc( lLong );
	if( pPacket == NULL ) {
		DebugLog("Failed To Alloc Memory!\n");
		goto _err;
	}

	lRealSize=TCP_Recv(sd,pPacket,lLong, nTimeOut);
	if( lRealSize<0 || lLong != lRealSize ) {
		free( pPacket );
		pPacket=NULL;
		DebugLog("packet size(%d!=%d) invalidation",lLong,lRealSize);
		goto _err;
	}
	return( pPacket );

_err:
	if(errflag!=NULL) {
		DebugLog("recv error. now will disconnect socket");
		*errflag = 1;  /* socket is disconnect */
	}
	return NULL;
}


/********************************************************************
 * NAME     : CheckRecvBuffer
 * FUNCTION : check recv buffer  if have data arrived 
 * PROCESS  : 1. set nonblock mode for socket 
 *          : 2. check receive buffer 
 * INPUT    : sd       : socket ID
 * OUTPUT   : 
 * UPDATE   :
 * RETURN   : -1    : buffer is empty
 *          : other : the packet size
 * AUTHOR	: ZZ-NODE/2000.12.18/songqufei
 * CALL     : ioctl()
 *          : recv()
 ********************************************************************/
int CheckRecvBuffer(int sd)
{
    int		rc,iLoop;
	PacketHead stHead;
	 
    rc = recv( sd, &stHead, sizeof(PacketHead), MSG_PEEK );
	if(rc < 0){		/* recv error */
		ErrorLog(COMMERR_TYPE,"SYSTEM","检查接收到的通信包时出错");
		return -1;
	}else if(rc != sizeof(PacketHead)){	/* received size error */
		for(iLoop=0;iLoop<20;iLoop++){
			rc = recv( sd, &stHead, sizeof(PacketHead), MSG_PEEK );
			if(rc < 0){
				ErrorLog(COMMERR_TYPE,"SYSTEM","检查接收到的通信包时出错");
				return -1;
			}else if(rc != sizeof(PacketHead)){
				continue;
			}else{
				break;
			}
		}
	}

	/* 检查是否仍然没收全 */
	if(rc != sizeof(PacketHead)){	/* 经过重试,收到的包依然不全 */
		DebugLog("Real received = %d,want receive = %d",rc,sizeof(PacketHead));
		ErrorLog(COMMERR_TYPE,"SYSTEM","检查接收到的通信包时出错");
		return -1;
	}

	/* 检查包的大小,不大于100M */
	if(stHead.lPacketSize > 100*1024*1024 || stHead.lPacketSize< sizeof(PacketHead)){
		ErrorLog(COMMERR_TYPE,"SYSTEM","收到的数据包过大。");
		ioctl(sd,I_FLUSH,FLUSHR);
		return -1;
	}
	/* 系统认证 */
	if(strcmp(stHead.sSystemID,SYSTEM_ID)){
		ErrorLog(COMMERR_TYPE,"SYSTEM","收到的数据包不属于本系统。");
		ioctl(sd,I_FLUSH,FLUSHR);
		return -1;
	}

    return stHead.lPacketSize;
}


/********************************************************************
 * NAME     : TCP_Recv
 * FUNCTION : recieve data by socket
 * PROCESS  : 1. receive all data in socket
 *          : 2. pack these data into a buffer
 * INPUT    : sd       : socket ID
 *          : pBuffer  : buffer used in store received data
 *          : lSize    : received size expected 
 *          : nTimeOut : time out ( seconds )
 * OUTPUT   : 
 * UPDATE   :
 * RETURN   : -1    : fail
 *          : other : received data real size
 * AUTHOR	: ZZ-NODE/2000.12.18/songqufei
 * CALL     : select()
 *          : recv()
 *          : ioctl()
 *          : FD_SET()
 ********************************************************************/
int TCP_Recv(int sd,char *pBuffer,int lSize,int nTimeOut  )
{
	int	iEachMaxSiz = 4096;		/* each received max size  */
	int	iEachRealSiz = 0;		/* each need receive  size  */
    int iTotalRecv = 0;			/* the total received bytes */
	int	iLeftSiz;				/* the left size */
    int	iSele,iRecv;			/* select return value, the received real size */
    
    fd_set    rd_set;
    struct timeval    tv;
    
    tv.tv_sec = nTimeOut;
    tv.tv_usec = 0;

	iLeftSiz = lSize;
	while(1){
		if(iLeftSiz<=0)	break;	/* 已经全部收完 */

		FD_ZERO(&rd_set);
		FD_SET(sd, &rd_set);
		iSele = (int) select(sd+1, &rd_set, NULL, NULL, &tv);
		if(iSele < 0) {
			DebugLog("接收数据包select出错。");
			ErrorLog(COMMERR_TYPE,"SYSTEM","接收数据包select出错。");
			return( -1 );
		}else if(iSele == 0) {
			DebugLog("接收数据包select超时");
			return (-1);
		}
		
		iEachRealSiz = iLeftSiz>iEachMaxSiz? iEachMaxSiz: iLeftSiz;
		iRecv = recv(sd,pBuffer,iEachRealSiz,0);
		if(iRecv < 0) {
			DebugLog("接收数据包recv出错。");
			ErrorLog(COMMERR_TYPE,"SYSTEM","接收数据包recv出错。");
			return( -1 );         
		}else if(iRecv == 0){
			break;	/* 没有收到想要收的东西,返回已经收到的内容 */
		}

		pBuffer += iRecv;		/* 修改buf指针 */
		iLeftSiz -= iRecv;		/* 重新计算剩余字节数 */
		iTotalRecv += iRecv;	/* 计算收到字节总数 */
	}

    return ( iTotalRecv );
}



/********************************************************************
 * NAME     : TCP_Close
 * FUNCTION : close socket
 * PROCESS  : 1. disable both send & receive
 *          : 2. close socket
 * INPUT    : sd : socket ID
 * OUTPUT   : 
 * UPDATE   :
 * RETURN   : 
 * AUTHOR	: ZZ-NODE/2000.12.18/songqufei
 * CALL     : close()
 *          : shutdown()
 ********************************************************************/
int TCP_Close(int sd )
{
	sleep(2);
    shutdown( sd, 2 );    /* disable both send & recv    */
	sleep(2);
    close( sd );
	sleep(2);
    return 0;
}

⌨️ 快捷键说明

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