1. 程式人生 > >C++socket客戶端select非同步連線傳送接收資料

C++socket客戶端select非同步連線傳送接收資料

這段時間公司專案一直用網口同底層裝置互動,顧記錄下,具體見程式碼:


int RFID_STANDARDPROTOCOL_API __stdcall Socket_SendAndRecv(SOCKET Socket, unsigned char * SendBuf
                                                       , unsigned char *RecvBuf, int send_len)
{
    int check_len = send_len - 1;

	int index;
	SendBuf[check_len] = 0;
	for(index = 0; index < check_len; index++)
	{
		SendBuf[check_len] += SendBuf[index];
	}
	SendBuf[check_len] = ~SendBuf[check_len] + 1;

	char recvbuf[1024]={0};

	fd_set fds;
	FD_ZERO(&fds);
	FD_SET(Socket, &fds);
	timeval time_out = {0, 0};
	
	switch(select(Socket + 1, &fds, NULL, NULL, &time_out))
	{
	case SOCKET_ERROR:
		break;
	case 0:
		break;
	default:
		{
			if (FD_ISSET(Socket, &fds))
			{
				recv(Socket, (char *)recvbuf, 1024, 0);
			}
		}
		break;

	}
	
	char *sendbuf = (char *)SendBuf;//將 unsigned char* 型別的 SendBuf 強制轉換為 char* 型別的 SendBuf

	if(send(Socket, sendbuf, send_len, 0) <= 0)
		return SENDERROR;

	
	int Lenth = 0;

	HANDLE hEventExit = NULL;
	WSAEVENT EventArray[2] = {WSACreateEvent(), hEventExit};
	WSAEventSelect(Socket, EventArray[0], FD_READ);
	
	DWORD dwWait = WSAWaitForMultipleEvents(1, EventArray, FALSE, 1000, FALSE);
	if (WAIT_OBJECT_0 == dwWait)
	{
		WSANETWORKEVENTS netEvents;
		if (SOCKET_ERROR == WSAEnumNetworkEvents(Socket, EventArray[0], &netEvents))
		{
			return -1;
		}
		if (!(netEvents.lNetworkEvents & FD_READ) || netEvents.iErrorCode[FD_READ_BIT])
		{
			return -1;
		}
		if((Lenth=recv(Socket, recvbuf, sizeof(recvbuf)-1, 0))<=0)
			return RECVERROR;
	}


	for(index = 0; index < Lenth; index++)
	{
		RecvBuf[index] = (unsigned char)recvbuf[index];	//將 char 型別的 RecvBuf 強制轉換為 unsigned  char 型別的 RecvBuf
	}
	if((RecvBuf[0] == 0x0B) && (RecvBuf[3] == 0))
		return SUCCESS;
	else
		return DATAERROR;
}
int RFID_STANDARDPROTOCOL_API __stdcall Socket_ConnectSocket(SOCKET *Socket, char *IPAddress, int Port)
{
    //載入套接字型檔
	WORD wVersionRequested;
	WSADATA wsaData;

	wVersionRequested = MAKEWORD(1, 1);

	if(WSAStartup(wVersionRequested, &wsaData) != 0)
	{
		return -1;
	}
	if(LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)
	{
		WSACleanup();
		return -1;
	}
	//建立套接字
	*Socket = socket(AF_INET, SOCK_STREAM, 0);
	if (*Socket == INVALID_SOCKET)
	{
		WSACleanup();
		return -3;
	}
	
	int TimeOut = 1000;			//設定傳送超時2秒
	if(::setsockopt(*Socket,SOL_SOCKET,SO_SNDTIMEO,(char *)&TimeOut,sizeof(TimeOut))==SOCKET_ERROR)
	{
		
	}

	TimeOut = 1000;			//設定接收超時2秒
	if(::setsockopt(*Socket,SOL_SOCKET,SO_RCVTIMEO,(char *)&TimeOut,sizeof(TimeOut))==SOCKET_ERROR)
	{
		
	}
	SOCKADDR_IN addrSrv;
	addrSrv.sin_addr.S_un.S_addr = inet_addr(IPAddress);
	addrSrv.sin_family = AF_INET;
	addrSrv.sin_port = htons(Port);

	//向伺服器傳送連線請求
#define __NONE_BLOCK_CONN__
	/* 非阻塞式連線 */
#ifdef __NONE_BLOCK_CONN__
	unsigned long mode = 1;
	int iRet = ioctlsocket(*Socket, FIONBIO, &mode);
	if (iRet != NO_ERROR)
	{
		
	}
	int conn_ret = connect(*Socket, (sockaddr *)&addrSrv, sizeof (sockaddr) );

	mode = 0;
	iRet = ioctlsocket(*Socket, FIONBIO, &mode);
	if (iRet != NO_ERROR)
	{

	}

	TIMEVAL timeval = {0};
	timeval.tv_sec = 0;
	timeval.tv_usec = 950 * 1000;

	fd_set Write, Err;
	FD_ZERO(&Write);
	FD_ZERO(&Err);
	FD_SET(*Socket, &Write);
	FD_SET(*Socket, &Err);

    
	select(*Socket + 1, NULL, &Write, &Err, &timeval);
	if(FD_ISSET(*Socket, &Write))
	{
		return SUCCESS;
	}
		// /* 阻塞式連線 */
#else
	if (connect(*Socket, (sockaddr *)&addrSrv, sizeof (SOCKADDR_IN) ) == 0)
	{
		return SUCCESS;
	}

#endif

	else
	{
		closesocket(*Socket);
		WSACleanup();

		return -2;
	}
}