📄 tcp_socket.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 + -