#include <stdio.h>
#include <taskLib.h>
#include <sockLib.h>
#include <inetLib.h>
#include <time.h>
#include <fcntl.h>
#include "NetFunc.h"
#define MS_TO_TIMEVAL(x, y) do { \
y.tv_sec = x / 1000; \
y.tv_usec = (x % 1000) * 1000; \
} while (0)
STATUS NET_SetFdAttr(int iFd, int iFlag)
{
int iVal;
int attr = 1;
if( ioctl(iFd, FIONBIO, &attr) < 0 )
{
perror("[net] ioctl failed");
return ERROR;
}
#if(0)
if ((iVal = fcntl(iFd, F_GETFL, 0)) < 0)
{
perror("[net] fcntl failed");
return ERROR;
}
iVal |= iFlag;
if (fcntl(iFd, F_SETFL, iVal) < 0)
{
perror("[net] fcntl failed");
return ERROR;
}
#endif
return OK;
}
/**
*@brief 创建UDP Socket
*
*@param[in] pDstIP目的IP地址
*@param[in] iDstPort目的端口
*@param[in] iLocalPort本地监听端口
*
*@return
*@retval -1 创建失败
*@retval 返回UDP socket操作句柄
*/
int NET_UDPBuildSocket(int iLocalPort)
{
int iSocketFd = -1;
int iRet = -1;
int opt = 1;
int iIndex = 0;
struct sockaddr_in localAddr;
iSocketFd = socket(AF_INET, SOCK_DGRAM, 0);
if (iSocketFd < 0)
{
perror("[net] UDPClient: opening socket failed ");
return (ERROR);
}
/* 本地网络地址 */
localAddr.sin_family = AF_INET;
localAddr.sin_len = SA_LEN;
localAddr.sin_port = htons(iLocalPort);
localAddr.sin_addr.s_addr = htonl(INADDR_ANY);
/*避免服务器出现意外而没有释放端口时,可以重新绑定端口,
否则会提示绑定失败*/
setsockopt(iSocketFd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
iRet = bind(iSocketFd, (struct sockaddr *) &localAddr, SA_LEN);
if (iRet == ERROR)
{
close(iSocketFd);
perror("[net] UDPServer: Failed to bind socket");
return (ERROR);
}
#if(0)
if (-1 == NET_SetFdAttr(iSocketFd, O_NONBLOCK))
{ //设置为非阻塞方式
close(iSocketFd);
return (ERROR);
}
#endif
return iSocketFd;
}
/**
*@brief UDP写入数据
*
*@param[in] iSocketFd UDP通信socket句柄
*@param[in] pDstIP 目的IP地址
*@param[in] iPort 目的端口
*@param[in] pBuff 存储了需要发送的数据
*@param[in] iSize 发送数据的长度
*@param[in] ms 写入数据的超时时间(单位为毫秒)。-1表示
*要成功写完所有数据才返回。0表示不管是否写完所有数据
*都立即返回。大于0表示写入数据的超时时间。
*
*@return 返回写数据状态
*@retval ERROR表示数据发送失败
*@retval OK表示数据发送成功
*/
STATUS NET_UDPWriteData(int iSocketFd, char *pDstIP, int iPort,
char *pBuff, int iSize, int ms)
{
int iRet = -1;
struct sockaddr_in saddr;
struct timeval tval;
fd_set write_set;
if( (iSocketFd < 0) || (NULL == pBuff) || (NULL == pDstIP))
{
return ERROR;
}
saddr.sin_family = AF_INET;
saddr.sin_len = SA_LEN;
saddr.sin_port = htons(iPort);
saddr.sin_addr.s_addr = inet_addr(pDstIP);
if (ms >= 0)//有超时时间
{
MS_TO_TIMEVAL(ms, tval);
}
while (1)
{
FD_ZERO(&write_set);
FD_SET(iSocketFd, &write_set);
iRet = select(iSocketFd + 1, NULL, &write_set,
NULL, (ms < 0) ? NULL : &tval);
if (-1 == iRet)
{ //select error
return ERROR;
}
else if (0 == iRet)
{ //time out
return ERROR;
}
else
{
if (FD_ISSET(iSocketFd, &write_set))
{ //可以发送报文
if (-1 != sendto(iSocketFd, pBuff,
iSize, 0, (struct sockaddr *) &saddr, SA_LEN))
{ //发送报文成功
return OK;
}
else
{
perror("[net] sendto failed ");
return ERROR;
}
}
}
}
return OK;
}
/**
*@brief UDP读取socket数据
*
*@param[in] iSocketFd UDP通信socket句柄
*@param[in] pBuff 存储数据空间
*@param[in] iSize 存储数据空间长度
*@param[in] ms 读取数据的超时时间(单位为毫秒)。-1表示
*要成功读取所有数据才返回。0表示不管是否读取所有数据
*都立即返回。大于0表示读取数据的超时时间。
*@param[out] pDstIP 目的IP地址
*
*@return 返回读取数据状态
*@retval ERROR表示数据读取失败
*@retval 0表示超时
*@retval 大于0表示读取到数据长度
*/
STATUS NET_UDPReadData(int iSocketFd, char *pBuff,
int iSize, int ms, char *pDstIP)
{
int iRet = -1;
int iAddrLen = SA_LEN;
int iRcvLen = 0;
struct timeval tval;
fd_set read_set;
struct sockaddr_in addr;
if( (iSocketFd < 0) || (NULL == pBuff) || (NULL == pDstIP))
{
return ERROR;
}
if (ms >= 0)//有超时时间
{
MS_TO_TIMEVAL(ms, tval);
}
while (1)
{
FD_ZERO(&read_set);
FD_SET(iSocketFd, &read_set);
iRet = select(iSocketFd + 1, &read_set, NULL, NULL,
(ms < 0) ? NULL : &tval);
if (-1 == iRet)
{ //select error
return ERROR;
}
else if (0 == iRet)
{ //time out
return 0;
}
else
{
if (FD_ISSET(iSocketFd, &read_set))
{ //接收到报文
iRcvLen = recvfrom(iSocketFd, pBuff, iSize,
0, (struct sockaddr *) &addr, &iAddrLen);
if (-1 != iRcvLen)
{ /* 成功接收到报文 */
snprintf(pDstIP, IP_ADDR_LEN, "%s",
inet_ntoa(addr.sin_addr));
//pAddress->sDesPort = addr.sin_port;
return iRcvLen;
}
else
{
perror("[net] recvfrom failed ");
return ERROR;
}
}
}
}
return OK;
}
/**
*@brief 创建TCP Client客户端
*
*@param[in] pDstIP tcp服务端IP地址
*@param[in] iPort 端口
*
*@return
*@retval -1 创建失败
*@retval socket操作句柄
*/
int NET_TCPBuildClientSocket(char *pDstIP, int iPort)
{
int iRet = -1;
int iSocketFd = -1;
struct sockaddr_in desAddr;
struct timeval wait;
if(NULL == pDstIP)
return ERROR;
iSocketFd = socket(AF_INET, SOCK_STREAM, 0);
if (iSocketFd < 0)
{
perror("[net] Failed to create TCP Client Socket ");
return ERROR;
}
#if(1)
if (-1 == NET_SetFdAttr(iSocketFd, O_NONBLOCK))
{ //设置为非阻塞方式
return (ERROR);
}
#endif
desAddr.sin_family = AF_INET;
desAddr.sin_len = SA_LEN;
desAddr.sin_port = htons(iPort);
desAddr.sin_addr.s_addr = inet_addr(pDstIP);
wait.tv_sec = 20;
wait.tv_usec = 0;
iRet = connectWithTimeout(iSocketFd, (struct sockaddr *) &desAddr,
SA_LEN, &wait);
if (iRet < 0)
{
close(iSocketFd);
perror("[net] Failed to connect TCP Server ");
return ERROR;
}
return iSocketFd;
}
/**
*@brief 创建TCP Server服务端
*
*@param[in] iPort 服务端监听端口,绑定地址为INADDR_ANY
*
*@return
*@retval -1 创建失败
*@retval socket操作句柄
*/
int NET_TCPBuildServerSocket(int iPort)
{
int iRet = -1;
int iSocketFd = -1;
int opt = 1;
struct sockaddr_in localAddr;
iSocketFd = socket(AF_INET, SOCK_STREAM, 0);
if (iSocketFd < 0)
{
perror("[net] Failed to create TCP Server Socket.\n");
return ERROR;
}
localAddr.sin_family = AF_INET;
localAddr.sin_len = SA_LEN;
localAddr.sin_port = htons(iPort);
localAddr.sin_addr.s_addr = htonl(INADDR_ANY);
/*避免服务器出现意外而没有释放端口时,可以重新绑定端口,
否则会提示绑定失败*/
setsockopt(iSocketFd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
iRet = bind(iSocketFd, (struct sockaddr *) &localAddr, SA_LEN);
if (iRet == ERROR)
{
close(iSocketFd);
perror("[net] Failed to bind TCP socket\n");
return ERROR;
}
iRet = listen(iSocketFd, 5);
if (iRet == ERROR)
{
close(iSocketFd);
perror("
评论0