udp_client_windows_c

/*****************************************************************************************
                                UDP客户端程序
文件:udpclient.h
功能:udp客户端程序
平台:VS2008
*****************************************************************************************/
#ifndef  _UDPCLIENT_H
#define  _UDPCLIENT_H
//****************************************************************************************
void UdpClientTest(void);
int  UdpClientInit(void);
void UdpClientClose(void);
int  UdpClientSend (const char *SdData , int SdLength);
int  UdpClientRecv (char *SdData , int SdLength , int timeout);
int  UdpClientRecvs(char *SdData , int SdLength , int timeout);
//****************************************************************************************
#endif

/*****************************************************************************************
                                UDP客户端程序
文件:udpclient.c
功能:udp客户端程序
平台:VS2008
编者:张永辉 2013年3月19日
添加: 添加UdpClientRecvs函数 2013年4月2日
*****************************************************************************************/
#include <Winsock2.h>                           //socket
#pragma  comment(lib,"ws2_32")
#include <stdio.h>                              //printf
#include  <windows.h>
#include <process.h>                            //thread
#include "udpclient.h"

//全局变量
SOCKET static   sSocket =   (SOCKET)NULL;
int   static    isOpend = 0;                    //连接是否已经关闭     ==0已经关闭
//int     static   SerThreadShuedClose = 0;     //服务线程是否需要关闭 ==0不需要
static char *   ServerIP = "10.169.66.205";     //服务器IP Port
u_short static  ServerPORT =    60012;
static struct   sockaddr_in saddr;              //创建地址结构,与IP Port相对应

/*****************************************************************************************
                                测试函数
*****************************************************************************************/
void UdpClientTest(void)
{
    char rev[200+1];
    int num;
    int cnt = 10;

    //初始化
    if(UdpClientInit()!=0)
    {   return; }

    //收发数据
    while (cnt--)
    {
        //发送数据
        UdpClientSend("zhangyonghui",12);
        printf("Send:zhangyonghui\n");
        //接收数据
        num = UdpClientRecv(rev,200,2000);
        rev[num] = '\0';
        printf("Rev Form Host:%s\n",rev);
        getchar();
    }
    //关闭连接
    UdpClientClose();
}

/*****************************************************************************************
返回:  0   成功,可以收发字节了
        1   加载库失败
        2   创建套接字失败
        3   连接到服务器失败
        4   已经初始化过了,无需要再次初始化
*****************************************************************************************/
int UdpClientInit(void)
{
    int err;
    WSADATA wsaData;
    WORD sockVersion;

    if(isOpend==1)
    {   return 4; }

    //加载winsock库
    sockVersion = MAKEWORD(2,2);            //使用2.2版本
    err = WSAStartup(sockVersion,&wsaData); //申请使用SOCKET,返回0表示成功,才可以使用其库函数。
    if(err!=0)
    {   isOpend = 0;
        return 1;
    }
    //创建socket
    sSocket = socket(   AF_INET,            //internetwork: UDP, TCP, etc
                        SOCK_DGRAM,         //网络协议类型,SOCK_DGRAM代表UDP协议,SOCK_STREAM代表TCP协议
                        IPPROTO_UDP);       //protocol 指定网络地址族的特殊协议,目前无用,赋值0即可
    if(sSocket==INVALID_SOCKET)             //INVALID_SOCKET表示创建失败
    {   WSACleanup();
        isOpend = 0;
        return 2;
    }
    saddr.sin_family = AF_INET;                         //AF_INET指定为TCP/IP协议族的套接字
    saddr.sin_port = htons(ServerPORT);                 //指明端口号 htons??
    //saddr.sin_addr.s_addr = htonl(INADDR_ANY);        //无论哪个网段的客户都能与其通讯。(与下句互斥)
    saddr.sin_addr.S_un.S_addr = inet_addr(ServerIP);   //固定IP,inet_addr()将字符串IP转换成整行IP
    //连接成功,connect返回0;失败则返回SOCKET_ERROR
    err = connect(sSocket,(struct sockaddr *)&saddr,sizeof(saddr));
    if(err == SOCKET_ERROR)
    {   closesocket(sSocket);
        WSACleanup();
        isOpend = 0;
        return 5;
    }

    isOpend = 1;
    return 0;
}
//关闭客户端
void UdpClientClose(void)
{
    if(isOpend==0)
    {   return; }
    closesocket(sSocket);   //关闭一个描述符为s套接字
    WSACleanup();           //最后一步:解除与Socket库的绑定并且释放Socket库所占用的系统资源
    isOpend = 0;
}

/*****************************************************************************************
                            发送数据函数
参数: *SdData  数据指针
      SdLength 数据长度
返回:0 发送失败 或发送了0个字节
      n 发送的字节数。
*****************************************************************************************/
int UdpClientSend(const char *SdData ,  int SdLength)
{
    int err;
    if(isOpend==0)
    {   return 0;   }

    err = sendto(sSocket,SdData,SdLength,0,(VOID*)&saddr,sizeof(saddr));
    if (err <0 )
    {   err = 0;
    }
    return err;
}
/*****************************************************************************************
                            接收数据函数
参数: *SdData  数据指针
      SdLength 数据长度
      timeout  超时时间,毫秒
返回:0 接收失败 或接收了0个字节
      n 接收的字节数。
*****************************************************************************************/
int UdpClientRecv(char *SdData , int SdLength , int timeout)
{
    int err = -1;
    int addrlen = sizeof(saddr);

    //超时接收需要的变量
    struct timeval tv;
    fd_set readfds;

    if(isOpend==0)
    {   return 0;   }

    //初始化等待时间
    tv.tv_sec = timeout/1000;           //秒
    tv.tv_usec = timeout%1000;          //微秒
    FD_ZERO(&readfds);
    FD_SET(sSocket, &readfds);

    //在此函数内进行等待
    select(sSocket+(SOCKET)1, &readfds, NULL, NULL, &tv);
    if (FD_ISSET(sSocket, &readfds))
    {   //从客户端接收消息
        err=recvfrom(sSocket,SdData,SdLength,0,(struct sockaddr*)&saddr,&addrlen);
        //recv(sSocket,ReData,ReLength,0);使用此函数接收也可以
    }

    if (err <0 )
    {   err = 0;    }
    return err;
}
/*****************************************************************************************
                            接收数据函数
参数: *SdData  数据指针
      SdLength 数据长度
      timeout  超时时间,毫秒
返回:0 接收失败 或接收了0个字节
      n 接收的字节数。
说明:UdpClientRecv  是接收一个数据包。若连续发了2包数据,则调用一次只能收一包。
      UdpClientRecvs 是接收在此时刻之前的收到的所有数据包。可能有多个包。
*****************************************************************************************/
int UdpClientRecvs(char *SdData , int SdLength , int timeout)
{
    int cnt;    //单次接收到的数据
    int unm = 0;    //总共接收到的数据
    cnt = UdpClientRecv(SdData,SdLength,timeout);
    unm = cnt;
    while(cnt!=0)
    {
        if(SdLength - unm < 0)
        {   //没有空间了,退出
            break;
        }
        cnt = UdpClientRecv(&SdData[unm],SdLength - unm,1);
        unm += cnt;

        //直到没有数据来了,才退出
        if(cnt<=0)
        {
            break;
        }
    }
    return unm;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值