我封装了一个udp的接口,有些地方还需要改进,但基本满足大部分的需求。 #流程介绍
函数介绍
sockfd
#include <sys/socket.h> sockfd = socket(int socket_family, int socket_type, int protocol); sockfd:描述符。 socket_family, 即协议域,又称为协议族(family)。常用的协议族有,AF_INET(IPV4)、AF_INET6(IPV6)、AF_LOCAL(或称AF_UNIX,Unix域socket)、AF_ROUTE等等。协议族决定了socket的地址类型,在通信中必须采用对应的地址,如AF_INET决定了要用ipv4 地址(32位的)与端口号(16位的)的组合、AF_UNIX决定了要用一个绝对路径名作为地址。 socket_type: 指定socket类型。常用的socket类型有,SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、SOCK_PACKET、SOCK_SEQPACKET等。 protocol:故名思意,就是指定协议。常用的协议有,IPPROTO_TCP、IPPTOTO_UDP、IPPROTO_SCTP、IPPROTO_TIPC等,它们分别对应TCP传输协议、UDP传输协议、STCP传输协议、TIPC传输协议。注意:并不是上面的type和protocol可以随意组合的,如SOCK_STREAM不可以跟IPPROTO_UDP组合。当protocol为0时,会自动选择type类型对应的默认协议。
inet_addr
#include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> in_addr_t inet_addr(const char *cp); 功能:用来将参数cp 所指的网络地址字符串转换成网络所使用的二进制数字。
htons
#include <arpa/inet.h> uint16_t htons(uint16_t hostshort); 功能:将主机的无符号短整形数转换成网络字节顺序
setsockopt
#include <sys/types.h> #include <sys/socket.h> int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen); sockfd :标识一个套接口的描述字。 level:选项定义的层次;目前仅支持SOL_SOCKET和IPPROTO_TCP层次。 optname:需设置的选项。 optval:指针,指向存放选项值的缓冲区。 optlen:optval缓冲区的长度。
bind
#include <sys/types.h> /* See NOTES */ #include <sys/socket.h> *int bind(int sockfd, const struct sockaddr addr, socklen_t addrlen);
封装文件.h
#ifndef _NETWORK_MULTICAST_H_
#define _NETWORK_MULTICAST_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#define DATASIZE (1024*10)
typedef struct user_recv_{
int code;
char data[DATASIZE];
int lenght;
void* user;
}UserRecv_S;
typedef enum networktype_{
UNICAST,
MULTICAST,
SPECAST,
}NetworkType_EN;
typedef struct os_netwoek{
char ip[16];
int port;
}Network_S ;
typedef void* (*HandleData)(void* recv_info);
typedef struct os_networmulticast{
NetworkType_EN entype;
Network_S stsrc_ip_info;
Network_S stdst_ip_info;
char amcast_ip[16];
int nmcast_port;
HandleData fnhandledata;
int nfd;
struct sockaddr_in stmucast_addr;
struct sockaddr_in stunque_addr;
int nflags;
struct timeval sttimeout;
int nrecv_opt;
int nsend_opt;
int nread_size;
UserRecv_S stuser_recv_handle;
int loopBack;
}NetworkMulticast_S;
int os_networkmulticast_init( NetworkMulticast_S* stpnetwork_info);
int os_networkmulticast_send(const char *pdata, int nlenght, NetworkMulticast_S* stpnetwork_info);
int os_networkunque_ip_send(const char *pdata, int nlenght, NetworkMulticast_S* stpnetwork_info, char* pip, int nport);
int os_networkunque_send(const char *pdata, int nlenght, NetworkMulticast_S* stpnetwork_info);
int os_networkmulticast_exit( NetworkMulticast_S* stpnetwork_info);
#ifdef __cplusplus
}
#endif
#endif
封装文件.C
#include"os_network_multicast.h"
static int os_network_socket(NetworkMulticast_S* stpnetwork_info)
{
int sockfd;
if( NULL == stpnetwork_info )
{
return -3;
}
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
struct sockaddr_in sock_addr, mucast_addr, unque_addr;
memset(&sock_addr, 0, sizeof(sock_addr));
memset(&mucast_addr, 0, sizeof(mucast_addr));
memset(&unque_addr, 0, sizeof(unque_addr));
sock_addr.sin_family = AF_INET;
if(stpnetwork_info->entype == UNICAST)
{
unque_addr.sin_family = AF_INET;
sock_addr.sin_addr.s_addr = inet_addr(stpnetwork_info->stsrc_ip_info.ip);
sock_addr.sin_port = htons(stpnetwork_info->stsrc_ip_info.port);
unque_addr.sin_addr.s_addr = inet_addr(stpnetwork_info->stdst_ip_info.ip);
unque_addr.sin_port = htons(stpnetwork_info->stdst_ip_info.port);
memcpy(&stpnetwork_info->stunque_addr, &unque_addr, sizeof(struct sockaddr_in));
}
else
{
mucast_addr.sin_family = AF_INET;
sock_addr.sin_addr.s_addr = INADDR_ANY;
sock_addr.sin_port = htons(stpnetwork_info->stsrc_ip_info.port);
mucast_addr.sin_addr.s_addr = inet_addr(stpnetwork_info->amcast_ip);
if( stpnetwork_info->nmcast_port <= 0)
{
mucast_addr.sin_port = htons(stpnetwork_info->stsrc_ip_info.port);
}
else
{
mucast_addr.sin_port = htons(stpnetwork_info->nmcast_port);
}
memcpy(&stpnetwork_info->stmucast_addr, &mucast_addr, sizeof(struct sockaddr_in));
}
if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &stpnetwork_info->sttimeout, sizeof(stpnetwork_info->sttimeout)) < 0)
{
perror("time out setting failed\n");
goto error;
}
int reuse = 1;
if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) < 0)
{
perror("Setting SO_REUSEADDR error");
goto error;
}
int ret = bind(sockfd, (struct sockaddr*)&sock_addr, sizeof(sock_addr));
if(-1 == ret)
{
perror("bind:");
goto error;
}
if(stpnetwork_info->entype == UNICAST)
{
stpnetwork_info->nfd =sockfd;
return 0;
}
int loopBack=stpnetwork_info->loopBack;
ret = setsockopt(sockfd,IPPROTO_IP, IP_MULTICAST_LOOP, &loopBack, sizeof(loopBack));
if(-1 == ret)
{
printf("setsockopt broadcaset error!!!\n");
perror("setsockopt:");
goto error;
}
if (stpnetwork_info->nrecv_opt > 0)
{
if (setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &stpnetwork_info->nrecv_opt, sizeof(int)) < 0)
{
printf("setsockopt error=%d(%s)!!!\n", errno, strerror(errno));
goto error;
}
}
if (stpnetwork_info->nsend_opt > 0)
{
if (setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &stpnetwork_info->nrecv_opt, sizeof(int)) < 0)
{
printf("setsockopt error=%d(%s)!!!\n", errno, strerror(errno));
goto error;
}
}
struct in_addr addr;
memset(&addr, 0, sizeof(addr));
if(stpnetwork_info->entype == MULTICAST)
{
addr.s_addr=INADDR_ANY;
}
else if(stpnetwork_info->entype == SPECAST)
{
addr.s_addr=inet_addr(stpnetwork_info->stsrc_ip_info.ip);
}
struct ip_mreq ipmr;
ipmr.imr_interface.s_addr = addr.s_addr;
ipmr.imr_multiaddr.s_addr = inet_addr(stpnetwork_info->amcast_ip);
ret=setsockopt(sockfd,IPPROTO_IP,IP_ADD_MEMBERSHIP,(const char*)&ipmr,sizeof(ipmr));
if (ret < 0)
{
perror("setsockopt():IP_ADD_MEMBERSHIP");
goto error;
}
if(stpnetwork_info->entype == SPECAST)
{
if(-1 == setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_IF, (char *)&addr, sizeof(addr)))
{
printf("set error IP_MULTICAST_IF %s\n", stpnetwork_info->amcast_ip);
perror("Setting IP_MULTICAST_IF error:");
goto error;
}
}
printf("socket success\n");
stpnetwork_info->nfd =sockfd;
return 0;
error:
if (sockfd >= 0)
{
close(sockfd);
}
return -1;
}
int os_networkunque_send(const char *pdata, int nlenght, NetworkMulticast_S* pNetwork_info)
{
int nsend_lenght=0, nret=0;
if( NULL == pdata )
{
return -1;
}
if( 0 >= nlenght )
{
return -2;
}
if( NULL == pNetwork_info )
{
return -3;
}
while( nsend_lenght < nlenght )
{
nret = sendto(pNetwork_info->nfd, pdata + nsend_lenght, nlenght-nsend_lenght, pNetwork_info->nflags, (struct sockaddr *)&(pNetwork_info->stunque_addr), sizeof(pNetwork_info->stunque_addr));
if(nret<0)
{
printf("os_networkunque_send error nRet[%d]\n",nret);
break;
}
if(nret == -1)
{
printf("send fail\n");
return -1;
}
nsend_lenght += nret;
}
return nsend_lenght;
}
int os_networkunque_ip_send(const char *pdata, int nlenght, NetworkMulticast_S* pNetwork_info, char* ip, int port)
{
if( NULL == pdata )
{
return -1;
}
if( 0 >= nlenght )
{
return -2;
}
if( NULL == pNetwork_info )
{
return -3;
}
if( NULL == ip )
{
return -4;
}
struct sockaddr_in seraddr;
seraddr.sin_family = AF_INET;
seraddr.sin_port = htons(port);
seraddr.sin_addr.s_addr = inet_addr(ip);
return sendto(pNetwork_info->nfd, pdata, nlenght, pNetwork_info->nflags, (struct sockaddr *)&(seraddr), sizeof(seraddr)) ;
int nsend_lenght=0, nret=0;
if(pdata == NULL)
return -1;
if(nlenght <=0)
return -2;
while( nsend_lenght < nlenght )
{
nret = sendto(pNetwork_info->nfd, pdata + nsend_lenght, nlenght-nsend_lenght, pNetwork_info->nflags, (struct sockaddr *)&(seraddr), sizeof(seraddr)) ;
nsend_lenght += nret;
if(nret == -1)
{
printf("send fail\n");
return -1;
}
}
return nsend_lenght;
}
int os_networkmulticast_send(const char *pdata, int nlenght, NetworkMulticast_S* pNetwork_info)
{
int nsend_lenght=0, nret=0;
if(pdata == NULL)
{
return -1;
}
if(nlenght <=0)
{
return -2;
}
if( NULL == pNetwork_info )
{
return -3;
}
while( nsend_lenght < nlenght )
{
nret =sendto(pNetwork_info->nfd, pdata + nsend_lenght, nlenght-nsend_lenght, pNetwork_info->nflags, (struct sockaddr *)&(pNetwork_info->stmucast_addr), sizeof(pNetwork_info->stmucast_addr)) ;
nsend_lenght+=nret;
if(nret == -1)
{
printf("send fail\n");
perror("send:");
return -1;
}
}
return nsend_lenght;
}
void* os_networkmulticast_recv(void* network_info1)
{
int nrecv_size = 0;
NetworkMulticast_S* stpnetwork_info = (NetworkMulticast_S* )network_info1;
if( stpnetwork_info == NULL)
{
return NULL;
}
if( stpnetwork_info->fnhandledata == NULL)
{
return NULL;
}
if( stpnetwork_info->nread_size <= 0 )
{
nrecv_size = DATASIZE;
}
else if( stpnetwork_info->nread_size >= DATASIZE )
{
nrecv_size = DATASIZE;
}
else
{
nrecv_size = stpnetwork_info->nread_size;
}
while (1)
{
int datalenght=0;
char data[DATASIZE];
struct sockaddr_in sock_addr;
memset(data, 0, DATASIZE);
memset(&sock_addr, 0, sizeof(sock_addr));
int addr_length=sizeof(sock_addr);
datalenght=recvfrom(stpnetwork_info->nfd, data, nrecv_size, 0, (struct sockaddr *)&sock_addr,(socklen_t*)&addr_length);
if(datalenght < 0)
{
break;
}
memcpy(stpnetwork_info->stuser_recv_handle.data, data, datalenght);
stpnetwork_info->stuser_recv_handle.lenght = datalenght;
stpnetwork_info->fnhandledata( &stpnetwork_info->stuser_recv_handle );
}
return NULL;
}
int os_networkmulticast_init(NetworkMulticast_S* stpnetwork_info)
{
os_network_socket(stpnetwork_info);
if( NULL == stpnetwork_info->fnhandledata)
{
return 0;
}
pthread_t tid;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
return pthread_create(&tid, &attr, os_networkmulticast_recv, (void*)stpnetwork_info);
}
int os_networkmulticast_exit( NetworkMulticast_S* stpnetwork_info )
{
if(close(stpnetwork_info->nfd) < 0)
{
printf("closesocket failed with error \n");
return 1;
}
return 0;
}
测试文件
#include"os_network_multicast.h"
NetworkMulticast_S network_info;
void* data_handle(void* recv_info1)
{
UserRecv_S* recv_info =(UserRecv_S*)recv_info1;
printf("数据:");
int i=0;
while(i < recv_info->lenght)
printf("%x ",recv_info->data[i++]);
printf("\n");
}
int main()
{
memset(&network_info, 0 ,sizeof(network_info));
network_info.entype=MULTICAST;
network_info.stsrc_ip_info.port=9099;
network_info.fnhandledata=data_handle;
strcpy(network_info.amcast_ip,"224.0.0.5");
os_networkmulticast_init(&network_info);
char aaaa[64] = {0};
while(1)
{
scanf("%s",aaaa);
os_networkmulticast_send(aaaa,strlen(aaaa),&network_info);
}
return 0;
}
|