📄 socketcom.cpp
字号:
// SocketCom.cpp: implementation of the CSocketCom class.
//
//////////////////////////////////////////////////////////////////////
//
#ifndef _XOPEN_SOURCE
#define _XOPEN_SOURCE 500 //Enable X/Open Unix98 namespace
#define _LARGEFILE_SOURCE
#define _LARGEFILE64_SOURCE
#define _FILE_OFFSET_BITS 64
#endif // #ifndef _XOPEN_SOURCE
#include <cstddef>
#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <errno.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include "socketcom.h"
volatile char t_socket_cfg_chg = 1;
volatile char t_exit;
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CSocketCom::CSocketCom()
{
m_socket = -1;
m_byComType = 2;//
m_wSendBytesPer = 2048;
}
CSocketCom::CSocketCom(int s)
{
m_socket = s;
m_byComType = 2;//
m_wSendBytesPer = 2048;
}
CSocketCom::~CSocketCom()
{
if(m_socket != -1)
close(m_socket);
m_socket = -1;
}
////////////////////////////////////////////////////////////////////////////////////////////
//SetComSet()
void CSocketCom::SetComSet(int addr, WORD wBytesPerFrame, BYTE byProtocol)
{
ADDR = (BYTE)addr;
m_wSendBytesPer = wBytesPerFrame;
m_byProtocol = byProtocol;
}
////////////////////////////////////////////////////////////////////////////////////////////
//SendData()发送数据
BOOL CSocketCom::SendData(unsigned char* buf, int length)
{
fd_set writefds;
struct timeval timeout;
timeout.tv_sec = 10;
timeout.tv_usec = 0;
FD_ZERO(&writefds);
FD_SET(m_socket, &writefds);
if(select(m_socket+1, NULL, &writefds, NULL, &timeout) == -1)//error
{
cout<<"SendData(): select()==-1, communication interrupt!"<<endl;
STATE = 2;//通讯中断
return FALSE;
}
if(!FD_ISSET(m_socket, &writefds))
return FALSE;
if(send(m_socket, buf, length, 0) == -1)
{
if(errno == EAGAIN)
return FALSE;
cout<<"SendData(): send()==-1, communication interrupt!"<<endl;
STATE = 2;//通讯中断
return FALSE;
}
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////////////////
//IsHaveData()读数据
BOOL CSocketCom::IsHaveData()
{
fd_set readfds;
struct timeval timeout;
timeout.tv_sec = 3;
timeout.tv_usec = 0;
FD_ZERO(&readfds);
FD_SET(m_socket, &readfds);
//readability means that queued data is available for reading such that a call to recv
//is guaranteed not to block
if(select(m_socket+1, &readfds, NULL, NULL, &timeout) == -1)
{
cout<<"IsHaveData(): select()==-1, communication interrupt!"<<endl;
STATE = 2;//通讯中断
return FALSE;
}
if(FD_ISSET(m_socket, &readfds))
return TRUE;
return FALSE;
}
///////////////////////////////////////////////////////////////////////////////////////////
//ReadData()读数据
int CSocketCom::ReadData(unsigned char* buf, WORD sec/*=10*/, WORD usec/*=0*/)
{
fd_set readfds;
struct timeval timeout;
int nBytesRead;
timeout.tv_sec = sec;
timeout.tv_usec = usec;
FD_ZERO(&readfds);
FD_SET(m_socket, &readfds);
//readability means that queued data is available for reading such that a call to recv
//is guaranteed not to block
if(select(m_socket+1, &readfds, NULL, NULL, &timeout) == -1)
{
cout<<"ReadData(): select()==-1, communication interrupt!"<<endl;
STATE = 2;//通讯中断
return -1;
}
if(!FD_ISSET(m_socket, &readfds))
return -1;
nBytesRead = recv(m_socket, buf, m_dwBufferSize, 0);
if(nBytesRead == -1)
{
if(errno == EAGAIN)
return -1;
cout<<"ReadData(): recv()==-1, communication interrupt!"<<endl;
STATE = 2;//通讯中断
return -1;
}
else if(nBytesRead == 0)//客户端关闭
{
cout<<"ReadData(): recv()==0, client close socket!"<<endl;
STATE = 2;//通讯中断
return -1;
}
return nBytesRead;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//socket_monitor_proc() 网口检测线程
void* socket_monitor_proc(void* pParam)
{
struct sockaddr_in sin;
struct sockaddr_in pin;
int sock_descriptor = -1;
int temp_sock_descriptor = -1;
int port = 0;
socklen_t sockaddrlen;
CSocketCom* pSocketCom;
fd_set readfds;
struct timeval timeout;
WORD wBytesPerFrame = 2000;
BYTE byProtocol = 0;
int flags;
//等待连接
while(1)
{
//查询是否退出
if(t_exit == 1)
break;
//查询是否配置已修改
if(t_socket_cfg_chg == 1)
{
t_socket_cfg_chg = 0;
//根据comconfig中包含的COM信息,初始化
CParameter* pParameter = GetParameter();
COMCONFIG comconfig;
pParameter->GetComConfig(&comconfig);
wBytesPerFrame = comconfig.wNetBytesPerFrame;
byProtocol = comconfig.byProtocol;
if(sock_descriptor==-1 || port!=(int)comconfig.dwThisPort)
{
port = comconfig.dwThisPort;
if(sock_descriptor != -1)
{
close(sock_descriptor);
sock_descriptor = -1;
}
sock_descriptor = socket(AF_INET, SOCK_STREAM, 0);
if(sock_descriptor == -1)
continue;
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = htonl(INADDR_ANY);
sin.sin_port = htons(port);
//Set the socket as non-blocking
flags = fcntl(sock_descriptor, F_GETFL, 0);
fcntl(sock_descriptor, F_SETFL, flags|O_NONBLOCK);
if(bind(sock_descriptor, (struct sockaddr*)&sin, sizeof(sin)) == -1) //与选定的端口绑定
continue;
if(listen(sock_descriptor, 200) == -1)//最多可同时200个连接
continue;
}
}
//检查套接字是否处于读状态,读状态表示有客户端正在连接(connect)
FD_ZERO(&readfds );
FD_SET(sock_descriptor, &readfds); // add sock to set
timeout.tv_sec = 2;
timeout.tv_usec = 0;
if(select(sock_descriptor+1, &readfds, NULL, NULL, &timeout) <= 0)
continue;
if(!FD_ISSET(sock_descriptor, &readfds))
continue;
sockaddrlen = sizeof(pin);
temp_sock_descriptor = accept(sock_descriptor, (struct sockaddr*)&pin, &sockaddrlen);
if(temp_sock_descriptor==-1 && errno==EAGAIN)
continue;
if(temp_sock_descriptor != -1)
{
cout<<"Server: Got connection from "<<inet_ntoa(pin.sin_addr)<<endl;
CParameter* pParameter = GetParameter();
SYSCONFIG sysconfig;
pParameter->GetSysConfig(&sysconfig);
pSocketCom = new CSocketCom(temp_sock_descriptor);
if(pSocketCom != NULL)
{
if(SOURCE == 0)
pSocketCom->SetComSet(atoi(sysconfig.chID), wBytesPerFrame, byProtocol+1);
else
pSocketCom->SetComSet(atoi(sysconfig.chID1), wBytesPerFrame, byProtocol+1);
pthread_t sock_response_thrd;
if(pthread_create(&sock_response_thrd, NULL, socket_response_proc, pSocketCom) != 0)
delete pSocketCom;
}
else
close(temp_sock_descriptor);
}
}
if(sock_descriptor != -1)
close(sock_descriptor);
return NULL;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//socket_response_proc() 网口响应线程
void* socket_response_proc(void* pParam)
{
pthread_detach(pthread_self());
CSocketCom* pCom = (CSocketCom*)pParam;
if(pCom == NULL)
return NULL;
//Set the socket as non-blocking
int flags = fcntl(pCom->m_socket, F_GETFL, 0);
fcntl(pCom->m_socket, F_SETFL, flags|O_NONBLOCK);
add_a_com_to_list(pCom);
if(pCom->m_byProtocol == 2)//浙江104
pCom->STATE = 1;
cout<<"Enter Socket Response Thread ..."<<endl;
time_t ttNow;
for(;;)
{
if(pCom->STATE == 2)//通讯中断
break;
if(pCom->m_force_exit == 1)//强制退出
{
pCom->m_force_exit = 0;
break;
}
if(pCom->IsHaveData())
pCom->Response();
else
{
ttNow = time(NULL);
if(ttNow > pCom->m_ttNewCom+2*60)//2 minutes
break;
}
if(t_exit == 1)
break;
}
cout<<"Exit Socket Response Thread ..."<<endl;
delete pCom;
return NULL;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -