socket网络编程实践要点

1、创建udp的socket句柄

// 当host_port为0时,则表示让操作系统自动分配
bool createUdpSocket(string host_ip,unsigned short host_port, int& sock_fd)
{
    sock_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if(sock_fd <= 0)
    {
        return false;
    }

    struct sockaddr_in client_addr= {0};
    inet_pton(AF_INET,host_ip.c_str(), &(client_addr.sin_addr));
    client_addr.sin_port =htons(host_port);
    client_addr.sin_family = AF_INET;

    if(::bind(sock_fd, (struct sockaddr*)&client_addr, sizeof(struct sockaddr_in))== -1)
    {
        close(sock_fd);
        sock_fd = -1;
        return false;
    }

    //获取操作系统分配的端口
    struct sockaddr_storage sock_addr;
    socklen_t addr_size = sizeof(struct sockaddr_storage);

    getsockname(sock_fd, (struct sockaddr*)&sock_addr, &addr_size);

    sockaddr_in sin ;
    memcpy(&sin,&sock_addr,addr_size);

    host_ip = inet_ntoa(sin.sin_addr);
    host_port = ntohs(sin.sin_port);

    // 设置socket为非阻塞
#ifdef WIN32
    unsigned long arg = 1;
    ioctlsocket(sock_fd, FIONBIO, &arg) ;
    ioctlsocket(sock_fd, FIONBIO, &arg) ;
#endif
#ifdef LINUX
    int arg = fcntl(sock_fd, F_GETFL, 0);
    fcntl(sock_fd, F_SETFL, arg | O_NONBLOCK);
#endif

    return true;

}

2、发送udp数据包

int sendUdpData(int socket_fd,char* buff,int buff_len,struct sockaddr* dest_addr)
{
    int count = 0 ;
    ssize_t send_len = 0;

    do
    {
        if(count > 0)
        {
            sleep_ms(5*count);
        }

        //考虑网络不好时,需要尝试发送多次
        send_len = sendto(socket_fd, buff, ssize_t(buff_len), 0, dest_addr, sizeof(struct sockaddr));
        count++;
    }while(send_len <0 && errno == EAGAIN && count<=5);
    return int(send_len);
}

3、发送udp广播包

int sendBroadUdpData(int sock_fd,char* buff,int buff_len)
{
    // 将端口设置为允许广播包
    int broadcast = 1;
#ifdef WIN32
    setsockopt(sock_fd, SOL_SOCKET, SO_BROADCAST, (const char *)&broadcast, sizeof(broadcast));
#else
    setsockopt(sock_fd, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(broadcast));
#endif

    struct sockaddr_in svr_addr;
    memset(&svr_addr, 0, sizeof(svr_addr));
    svr_addr.sin_family = AF_INET;
    svr_addr.sin_port = htons(BROAD_CAST_PORT);

    int server_ip;
    inet_pton(AF_INET, "255.255.255.255", (void *)&server_ip);
    svr_addr.sin_addr.s_addr = server_ip;

    sendUdpData(sock_fd, buff, buff_len, (struct sockaddr*)&svr_addr);

}

4、接收udp的数据包
利用poll或epoll模型,当某个socket_fd有数据可读时,即可返回进行相应的处理

{
    struct sockaddr_in client_addr;
    int len = sizeof(struct sockaddr);
    char recv_buff[1024];
    int recv_len = 0;

    recv_len = recvfrom(socket_fd, recv_buff, sizeof(recv_buff), 0, (struct sockaddr *)&client_addr, (socklen_t *)&len)
    if (recv_len > 0)
    {
        processMsg(recv_buff, recv_len, client_addr);
    }
}

5、poll模型的构建,同时监控多个fd

{
    int maxCount = 20;
#ifdef LINUX
    struct pollfd wait_fd[maxCount];
#endif

#ifdef WIN32
    WSAPOLLFD wait_fd[maxCount];
#endif

    int real_count = 0;

    listen_fds.clear();
    GetListenFd(listen_fds);
    for (int index = 0; index < (int)listen_fds.size(); index++)
    {
        wait_fd[real_count].fd = listen_fds[index];
        wait_fd[real_count].events = POLLIN | POLLOUT;
        real_count++;
    }

#ifdef LINUX
    int res = ::poll(wait_fd, real_count, 100); //100毫秒超时
#endif

#ifdef WIN32
    int res = WSAPoll(wait_fd, real_count, 100);
#endif

    if (res == -1)
    {
        usleep(10000);
    }
    else if (res)
    {
        int current_fd;
        for (int index = 0; index < real_count; index++)
        {
            current_fd = wait_fd[index].fd;
            if ((wait_fd[index].revents & POLLIN) > 0)
            {
                recvfrom(current_fd, recv_buff, sizeof(recv_buff), 0, (struct sockaddr *)&client_addr, (socklen_t *)&alen);

                bool is_listen_fd = false; //是否是监听句柄
                for (int pos = 0; pos < (int)listen_fds.size(); pos++)
                {
                    if (current_fd == listen_fds[pos])
                    {
                        is_listen_fd = true;
                        break;
                    }
                }
            }

            if ((wait_fd[index].revents & POLLERR) > 0)

                usleep(10000);
            }
        }
    }
    else
    {
        printf("time out.\n");
    }

}

原文地址:https://www.cnblogs.com/share-ideas/p/10886689.html

时间: 2024-10-09 10:43:43

socket网络编程实践要点的相关文章

Java之Socket网络编程实践

转自:http://my.oschina.net/leejun2005/blog/104955#comments 一.TCP/IP协议 既然是网络编程,涉及几个系统之间的交互,那么首先要考虑的是如何准确的定位到网络上的一台或几台主机,另一个是如何进行可靠高效的数据传输.这里就要使用到TCP/IP协议. TCP/IP协议(传输控制协议)由网络层的IP协议和传输层的TCP协议组成.IP层负责网络主机的定位,数据传输的路由,由IP地址可以唯一的确定Internet上的一台主机.TCP层负责面向应用的可

Socket网络编程 详细过程(转)

我们深谙信息交流的价值,那网络中进程之间如何通信,如我们每天打开浏览器浏览网页时,浏览器的进程怎么与web服务器通信的?当你用QQ聊天时,QQ进程怎么与服务器或你好友所在的QQ进程通信?这些都得靠socket?那什么是socket?socket的类型有哪些?还有socket的基本函数,这些都是本文想介绍的.本文的主要内容如下: 1.网络中进程之间如何通信? 2.Socket是什么? 3.socket的基本操作 3.1.socket()函数 3.2.bind()函数 3.3.listen().co

socket网络编程的一些基础知识

源地址:http://blog.csdn.net/roger_77/article/details/1453049 目录: 1) 什么是套接字? 2) Internet 套接字的两种类型 3) 网络理论 4) 结构体 5) 本机转换 6) IP 地址和如何处理它们 7) socket()函数 8) bind()函数 9) connect()函数 10) listen()函数 11) accept()函数 12) send()和recv()函数 13) sendto()和recvfrom()函数 

socket 网络编程快速入门(一)教你编写基于UDP/TCP的服务(客户端)通信

因为UNIX和Win的socket大同小异,为了方便和大众化,这里先介绍Winsock编程. socket 网络编程的难点在入门的时候就是对基本函数的了解和使用,因为这些函数的结构往往比较复杂,参数大部分都是结构体,令人难以记忆和理解. 但是一旦我们知道这些函数包括其参数的具体含义,socket网络编程也就变得不是那么复杂.这里不赘述 具体函数的详细含义,网络上有很多的文章,同时笔者建议大家参考 MSDN,对返回值,参数等会有更好的理解. 以下均为单线程的简单实例,多线程的请关注下一篇文章. (

Socket网络编程--网络爬虫(1)

我们这个系列准备讲一下--网络爬虫.网络爬虫是搜索引擎系统中十分重要的组成部分,它负责从互联网中搜集网页,采集信息,这些网页信息用于建立索引从而为搜索引擎提供支持,它决定着整个引擎系统的内容是否丰富,信息是否即时,因此其性能的优劣直接影响着搜索引擎的效果.网络爬虫的基本工作原理: (1)从一个初始URL集合中挑选一个URL,下载该URL对应的页面: (2)解析该页面,从该页面中抽取出其包含的URL集合,接下来将抽取的URL集合再添加到初始URL集合中: (3)重复前两个过程,直到爬虫达到某种停止

windows下的socket网络编程(入门级)

windows下的socket网络编程 clinet.c 客户端 server.c 服务器端 UDP通信的实现 代码如下 已经很久没有在windows下编程了,这次因为需要做一个跨平台的网络程序,就先写了个简单的winSocket网路通信的例子,以便以后用到的时候有个参考. windows下使用winsock编程与linux/unix的区别在于windows下需要先有一个初始化的操作,结束的时候需要一个清理的操作.还有windows下编译的时候需要连接ws32_lib库. 大致过程如下 1.初始

Linux Socket 网络编程

Linux下的网络编程指的是socket套接字编程,入门比较简单.在学校里学过一些皮毛,平时就是自学玩,没有见识过真正的socket编程大程序,比较遗憾.总感觉每次看的时候都有收获,但是每次看完了之后,过段时间不看,重新拾起这些知识的时候又要从头开始,所以,在这里做个笔记也算是做个模板,以后可以直接从某一个阶段开始接着玩... 1. socket套接字介绍 socket机制其实就是包括socket, bind, listen, connect, accept等函数的方法,其通过指定的函数实现不同

linux下C语言socket网络编程简例

转自:http://blog.csdn.net/kikilizhm/article/details/7858405 这里给出在linux下的简单socket网络编程的实例,使用tcp协议进行通信,服务端进行监听,在收到客户端的连接后,发送数据给客户端:客户端在接受到数据后打印出来,然后关闭.程序里有详细的说明,其中对具体的结构体和函数的实现可以参考其他资料. 程序说明: 这里服务器的端口号和ip地址使用固定的设置,移植时可以根据具体情况更改,可以改写为参数传递更好,这里为了方便,使用固定的. 移

Socket网络编程初探

MarkdownPad Document Socket网络编程初探 客户端/服务器架构 即C/S架构,其实web服务在某种意义上也算是C/S架构 一个特点是服务器端持续运行对外提供服务 为何学习socket一定要先学习互联网协议: C/S架构的软件是基于网络进行通信的 网络的核心就是一堆协议,即标准,想要开发一款基于网络通信的软件就必须遵循这些标准 socket是处在应用层和传输层中间的一组接口 说到这,那么socket到底是个什么呢?Socket是应用层与TCP/IP协议族通信的中间软件抽象层