定时连接socket函数封装

connect_timo函数,给定timeout秒内连接服务端,0成功,其它失败;

writen函数,阻塞写n个字节, 返回实际读取的字节数;

readn函数,可以设置超时限制,在超时时间内阻塞读取n个字节,返回实际读取 的字节数。

readn和writen封装函数的意义:不少初学者容易犯这样的错误,调用send或recv不检查返回值 。这跟不熟悉TCP和操作系统的特性有关,TCP是可以分片的,操作系统的buffer也是有限制的,一次阻塞send 调用未必可以将所希望的长度写完(虽然仅仅是写到操作系统buffer而已),一次阻塞recv调用读取到的也未 必是所指定的读取长度(但现在版本glibc的recv函数flags参数支持MSG_WAITALL了)。

--- 贴代码 tcp_util.c ---

/*
 * tcp_util.c    tpc sock utils module
 * Author    Digger Wu (digger.wu@gmail.com)
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <fcntl.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>

/*
 * connect within given timeout
 */
int
connect_timo(struct in_addr addr, u_short port, int seconds)
{
    struct sockaddr_in server;
    int sock;
    fd_set fdw;
    struct timeval timeout;
    int fflag;
    int errcode;
    int errlen;

    bzero(&server, sizeof(server));
    server.sin_family = AF_INET;
    server.sin_port = htons(port);
    server.sin_addr.s_addr = addr.s_addr;

    if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
        return -1;
    }

    if ((fflag = fcntl(sock, F_GETFL, 0)) < 0) {
        close(sock);
        return -2;
    }

    if (fcntl(sock, F_SETFL, fflag|O_NDELAY) < 0) {
        close(sock);
        return -3;
    }

    connect(sock, (struct sockaddr *)&server, sizeof(server));

    timeout.tv_sec = seconds;
    timeout.tv_usec = 0;
    FD_ZERO(&fdw);
    FD_SET(sock, &fdw);

      CNNT_AGAIN:

    switch (select(sock + 1, NULL, &fdw, NULL, &timeout)) {

    case -1:
        if (errno == EINTR)
            goto CNNT_AGAIN;
        close(sock);
        return -4;

    case 0:
        close(sock);
        return -5;

    default:
        if (FD_ISSET(sock, &fdw)) {
            errlen = sizeof(errcode);
            if (getsockopt(sock, SOL_SOCKET, SO_ERROR,
                       &errcode, (socklen_t *)&errlen) < 0) {
                close(sock);
                return -6;
            }
            if (errcode == 0) {
                if (fcntl(sock, F_SETFL, fflag) < 0) {
                    close(sock);
                    return -7;
                }
                return (sock);
            } else {
                close(sock);
                return -8;
            }
        }
    }
    return -1;
}

/*
 * write exactly n chars
 */
int
writen(int fd, char *buffer, int length)
{
    char *ptr;
    int n, left = length;

    ptr = buffer;
    while (left) {
        if ((n = send(fd, ptr, left, 0)) > 0) {
            left -= n;
            ptr += n;
        } else
            return -1;
    }
    return length;
}

/*
 * read exactly n chars within given timeout
 */
int
readn(int fd, char *buffer, int length, int timo)
{
    char *ptr;
    int n, left = length;
    fd_set fds;
    int i, res, maxrcv = 16;
    struct timeval wait;

    wait.tv_sec = timo;
    wait.tv_usec = 0;

    if (length > 1024 * 16)
        maxrcv = length / 1024;

    ptr = buffer;
    i = 0;
    while (i++ < maxrcv && left != 0) {
        FD_ZERO(&fds);
        FD_SET(fd, &fds);

        res = select(fd + 1, &fds, NULL, NULL, &wait);
        if (res < 0) {
            if (errno == EINTR) continue;
            return -1;
        } else if (res == 0) {
            return (length - left);
        }

        n = recv(fd, ptr, left, 0);
        if (n > 0) {
            left -= n;
            ptr += n;
        } else if (n == 0) {
            return (length - left);
        } else {
            return -1;
        }
    }
    return (length - left);
}

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索int
, include
, send recv
, return
, length
, sock
, left
, Errcode
定时读取
socket定时重连接、socket连接函数、websocket定时推送、websocket 定时器、socket.io 定时器,以便于您获取更多的相关知识。

时间: 2024-09-18 20:36:26

定时连接socket函数封装的相关文章

linux网络编程之socket(二) C/S程序的一般流程和基本socket函数

一.基于TCP协议的网络程序 下图是基于TCP协议的客户端/服务器程序的一般流程: 服务器调用socket().bind() .listen()完成初始化后,调用accept()阻塞等待,处于监听端口的状态,客户端调用socket()初始化后,调用connect() 发出SYN段并阻塞等待服务器应答,服务器应答一个SYN-ACK段,客户端收到后从connect()返回,同时应答一个ACK段,服务 器收到后从accept()返回. 数据传输的过程: 建立连接后,TCP协议提供全双工的通信服务,但是

msdos-socket-MSDOS下socket编程客户端 socket()函数的errno=123

问题描述 MSDOS下socket编程客户端 socket()函数的errno=123 我在MSDOS下编写了一个socket程序,运行于MSDOS71下是可以对一个服务端仿真建立连接的. 然后将程序放在win98下的msdos运行,在socket()获取套接字时errno返回123,但是我在win98下telnet或ping这个服务端仿真都是可以通的. 是否是因为,我win98下的msdos没有安装network client的原因?这个errno=123具体原因是什么? 解决方案 VC++中

python定时执行指定函数的方法

  本文实例讲述了python定时执行指定函数的方法.分享给大家供大家参考.具体实现方法如下: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 # time a function using time.time() and the a @ function decorator # tested with

路由器怎么设置定时连接模式

  路由器怎么设置定时连接模式          1.在浏览器地址栏中输入192.168.1.1或者192.168.0.1,具体可以看路由器底部的说明,点击回车; 2.输入管理员密码进行登录; 3.依次点击左侧导航:网络参数--WAN口设置; 4.在连接模式中选择"定时连接,在指定时间段自动连接"; 5.再根据自己的需要设置时间段,并点击保存; 6.为确保时间准确,需要设置一下路由器的时间,点击左侧的系统工具--时间设置; 7.先选择时区,再设置当前时区的当地时间,设置好后,点击保存,

CI框架常用函数封装实例_php实例

本文实例讲述了CI框架常用函数封装.分享给大家供大家参考,具体如下: /** * 封装查询函数 */ public function get_what($table='',$where=array(),$fields = ' * '){ if( '' == $table ){ return false; } //查询并返回相关结果 $query = $this->db->select($fields)->where($where)->get($table); $res = $que

oracle-C++调用创建连接池函数createStatelessConnectionPool崩溃

问题描述 C++调用创建连接池函数createStatelessConnectionPool崩溃 解决方案 访问了错误的指针,你createStatelessConnectionPool函数中有参数没有给正确赋值等 解决方案二: 编译成exe,以管理员身份运行一下试试,看是不是因为权限的问题 解决方案三: 我猜测是不是可以用gelasterror输出一下,最后是啥情况造成的错误呢?

operation-求大神解释一下socket函数中出现Operation not permitted原因

问题描述 求大神解释一下socket函数中出现Operation not permitted原因 54 int s = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP)); 55 if(s < 0) 56 { 57 perror("socket"); 58 return -1; 59 } 源码是这样的

PHP持久连接mysql_pconnect()函数使用介绍_php技巧

mysql_pconnect在单一进程,特别是一直保持执行的监控程序,特别适用. mysql_pconnect用法和mysql_connect类似: 复制代码 代码如下: <?php $conn = mysql_pconnect($host,$user,$pwd); mysql_select_db($dbname,$conn); $result=mysql_query("select * from table_name where col_id ='test_id'", $con

JavaScript中cookie工具函数封装的示例代码_javascript技巧

一. 语法 1.1 获取当前页面的所有cookie: var allCookies = document.cookie; allCookies 是一个字符串,其中包含了以分号分隔的cookie列表字符串 (即 key=value 键值对). 1.2 写一个新cookie: document.cookie = updatedCookie; updatedCookie是一个键值对形式的字符串.只能用这个方法一次设置或更新一个cookie,而且写入并不是覆盖,而是添加.例如: document.coo