udp service client

#python udp client

#!/usr/bin/python
# -*- coding: UTF-8 -*-
#

from socket import *
import os
import time

HOST = 'localhost'
PORT = 5015
BUFSIZE = 1024
ADDR = (HOST, 5014)

def main():
udpCliSock = socket(AF_INET, SOCK_DGRAM)
udpCliSock.bind(ADDR)
for i in xrange(0,10):
udpCliSock.sendto(str(i),('localhost',PORT))
print "success"
time.sleep(1)
pass
udpCliSock.close()

if __name__ == '__main__':
main()

 

说一下这几天折腾Udp通讯相关心得

 

#客户端在创建udp socket后,也需要先bind一个端口,不然发送到服务器的udp包,服务器解出来的端口号是不固定的。这应该是和协议的实现有关,和TCP不同,TCP客户端不需要bind。

#bind的端口和发送的端口号可以是不一样的。

void* runNet(void* data)

{

    CCLOG("runNet,begin!");

    sleep(1);

    //设置可以由主线程取消子线程

    if (pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0)

    {

        CCAssert(false, "UdpServer runNet set PTHREAD_CANCEL_ENABLE error");

    }

    if (pthread_setcancelstate(PTHREAD_CANCEL_ASYNCHRONOUS, NULL) != 0)

    {

        CCAssert(false, "UdpServer runNet set PTHREAD_CANCEL_ASYNCHRONOUS error");

    }

    UdpServer* _udpsever = (UdpServer*)data;

    

    struct event_base *base;

    struct event *signal_event;

    struct event *data_event;

    struct event *wakeup_event;

    evutil_socket_t fd = -1;

    int flag = 1;

    int result = 0;

    struct sockaddr_in sin;

#ifdef WIN32

    WSADATA wsa_data;

    WSAStartup(0x0201, &wsa_data);

#endif

    

    base = event_base_new();

    if (!base) {

        CCLOG("runNet,Could not initialize libevent!\n");

        return 0;

    }

    //set udp socket,bind port

    fd = socket(AF_INET, SOCK_DGRAM, 0);

    if ( fd < 0) {

        evutil_closesocket(fd);

        CCLOG("runNet can't create socket\n");

        return 0;

    }

    if (evutil_make_socket_nonblocking(fd) < 0) {

        evutil_closesocket(fd);

        CCLOG("runNet can't set socket nonblocking\n");

        return 0;

    }

    /* Set socket option */

    result=setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*)&flag, sizeof(flag));

    if (result < 0) {

        evutil_closesocket(fd);

        CCLOG("runNet setsockopt() error:%d\n",result);

        return 0;

    }

    

    memset(&sin, 0, sizeof(sin));

    sin.sin_family = AF_INET;

    sin.sin_addr.s_addr = inet_addr(IPADDRESS);

    sin.sin_port = htons(PORT);

    if (bind(fd, (struct sockaddr *)&sin, sizeof(struct sockaddr)) < 0) {

        evutil_closesocket(fd);

        CCLOG("runNet bind() error\n");

        return 0;

    } else {

        CCLOG("runNet bind() success - [%s] [%d]\n", IPADDRESS, PORT);

    }

    

    //set fd event

    data_event=event_new(base, fd, EV_READ | EV_PERSIST, &read_cb, (void*)_udpsever);

    if (!data_event || event_add(data_event, NULL)<0) {

        evutil_closesocket(fd);

        CCLOG("runNet Could not create/add a read Socket event!\n");

        return 0;

    }

    _udpsever->socket = fd;

    //set signal event,ctrl+c

    signal_event = evsignal_new(base, SIGINT, signal_cb, (void *)base);

    if (!signal_event || event_add(signal_event, NULL)<0) {

        evutil_closesocket(fd);

        CCLOG("runNet Could not create/add a signal event!\n");

        return 0;

    }

    

    //wakeup

#ifdef WIN32

#define LOCAL_SOCKETPAIR_AF AF_INET

#else

#define LOCAL_SOCKETPAIR_AF AF_UNIX

#endif

    evutil_socketpair(LOCAL_SOCKETPAIR_AF, SOCK_STREAM, 0, s_wakeupSocket);

    wakeup_event = event_new(base, s_wakeupSocket[1], EV_READ | EV_PERSIST, wakeup_cb, (void*)_udpsever);

    if (!wakeup_event || event_add(wakeup_event, NULL)<0)

    {

        evutil_closesocket(s_wakeupSocket[0]);

        evutil_closesocket(s_wakeupSocket[1]);

        CCLOG("runNet Could not create/add wakeup_event!\n");

        return 0;

    }

    

    event_base_dispatch(base);

    event_free(signal_event);

    event_base_free(base);

    

    CCLOG("UdpServer runNet function exit\n");

    return 0;

}

static void read_cb(evutil_socket_t fd, short event, void *userData)

{

    UdpServer* _udpServer = (UdpServer*)userData;

    char buf[BUF_SIZE];

    int size = sizeof(struct sockaddr);

    struct sockaddr_in  client_addr;

    

    memset(buf, 0, sizeof(buf));

    int len = recvfrom(_udpServer->socket,buf,BUF_SIZE,0,(struct sockaddr *)&client_addr,(socklen_t *)&size);

    

    if (len == -1) {

        CCLOG("udpSever recvfrom() error\n");

    } else if (len == 0) {

        CCLOG("udpSever Connection Closed\n");

    } else {

        MessageCenter* _msgC = _udpServer->getMessageCenter();

        if(_msgC != NULL)

        {

            long ip = client_addr.sin_addr.s_addr;

//          CCLOG("udpSever Read: len [%d] - content [%s] ipxxxxxxx:[%s]\n", len,buf,inet_ntoa(client_addr.sin_addr));

            int port = ntohs(client_addr.sin_port);

            CCLOG("udpSever Read: len [%d] - content [%s] ip:[%ld]  port:[%d]\n", len, buf,ip,port);

            MessageNode* _msgN = MessageNode::create(buf, len,ip,port);

            _msgC->addMsgNode_RecvMsgQueue(_msgN);

        }

        /* Echo */

        //sendto(fd, buf, len, 0, (struct sockaddr *)&client_addr, size);

    }

}

static void signal_cb(evutil_socket_t sig, short events, void *user_data)

{

    struct event_base *base = (struct event_base *)user_data;

    struct timeval delay = {1,0};

    

    printf("Caught an interrupt signal; exiting cleanly in two seconds.\n");

    

    event_base_loopexit(base, &delay);

}

static void wakeup_cb(evutil_socket_t pairSocketId, short event, void *user_data)

{

    UdpServer* _udpServer = (UdpServer*) user_data;

    int size = sizeof(struct sockaddr);

    evutil_socket_t fd = _udpServer->socket;

    struct sockaddr_in sin;

    MessageCenter* _msgC =  _udpServer->getMessageCenter();

    QueueMsgNode* _msgQ = _udpServer->msgQueue;

    _msgC->get_SendMsgQueue(_msgQ);

    QueueMsgNode::iterator it;

    

    for (it=_msgQ->begin(); it!=_msgQ->end(); it++)

    {

        MessageNode* tmp = *it;

        memset(&sin, 0, sizeof(sin));

        sin.sin_family = AF_INET;

        sin.sin_addr.s_addr = tmp->ip;

        sin.sin_port = tmp->port;

        CCLOG("wakeup_cb send---ip:%ld,port:%d,msg:%s \n",tmp->ip,tmp->port,tmp->msgPtr);

        sendto(fd, tmp->msgPtr, tmp->msgLen, 0, (struct sockaddr *)&sin, size);

        

        //谁用谁删除

        delete tmp;

    }

    _msgQ->clear();

}

 #贴一个用libevent写的server端。

 

posted @ 2014-12-18 18:11  城市*斗士(技术)  阅读(408)  评论(0编辑  收藏  举报