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

📄 socketcom.cpp

📁 linux下socket编程源码
💻 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 + -