Chinaunix首页 | 论坛 | 博客
  • 博客访问: 67872
  • 博文数量: 8
  • 博客积分: 1416
  • 博客等级: 上尉
  • 技术积分: 90
  • 用 户 组: 普通用户
  • 注册时间: 2009-10-21 22:35
个人简介

The best or nothing!

文章分类

全部博文(8)

文章存档

2020年(1)

2015年(3)

2011年(3)

2010年(1)

分类: LINUX

2011-07-07 18:42:29

       send本身是非阻塞的,不会产生超时错误(其实send操作与接收端没有关系, send返回的错误都是侦测到的本地错误). 但是如果send buffer(在每个socket的struct sock结构体中定义的有send buffer大小)被填满了并且socket是可阻塞的, 则send阻塞应用程序的执行. 如果socket是不可阻塞的, 则send buffer满后send立即返回EAGAIN or EWOULDBLOCK错误.
       当我们设置了socket的SO_SNDTIMEO选项时, 一旦send buffer被写满, 则send在达到发送超时时间后返回, 但是不会产生错误, 应用程序会继续进行其他的send or recv操作. 下面是一段测试代码:

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

extern int errno;

int main(void) {
    struct sockaddr_in server_addr;
    socklen_t server_addr_len = sizeof(struct sockaddr_in);
    int listen_fd, connected_fd;
    int retval;
    struct timeval timeout;
    char buf[103425];
    memset(buf, 'c', 103425);
    buf[103424] = '\0';

    listen_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (listen_fd < 0)
        perror("socket() error");

    connected_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (connected_fd < 0)
        perror("socket() error");

    if (listen(listen_fd, 5) < 0)
        perror("listen() error");

    if (fork() == 0) {
        struct sockaddr_in originating_addr;
        socklen_t originating_addr_len = sizeof(struct sockaddr_in);
        int accepted_fd;

        /* Accept the connection, wait for it to be closed, then die. */
        accepted_fd = accept(listen_fd, (struct sockaddr*) &originating_addr,
                                        &originating_addr_len);
        if (accepted_fd < 0)
            perror("accept() error");

        /* We can use fcntl() to set socket's block mode. */

        /*
        int fl = fcntl(accepted_fd, F_GETFL, 0);
        if (fl == -1)
            perror("fcntl() error");

        fcntl(accepted_fd, F_SETFL, fl& ~O_NONBLOCK);
        */

        timeout.tv_sec = 10;
        timeout.tv_usec = 0;
        if (setsockopt(accepted_fd, SOL_SOCKET, SO_SNDTIMEO, &timeout,
                             sizeof(struct timeval)) < 0)
            perror("setsockopt() error");

        int j;
        for (j = 0; j < 10; j++) {
            retval = send(accepted_fd, buf, 103425, 0);
            if (retval < 0) {
                perror("Child: send error");
            } else
                printf("Child: send %d bytes\n", retval);
        }
        return 0;
    }
    
    if (getsockname(listen_fd, (struct sockaddr*) &server_addr,
                           &server_addr_len) < 0)
        perror("getsockname() error");
    if (connect(connected_fd, (struct sockaddr*) &server_addr,
                       server_addr_len) < 0)
        perror("connect() error");

    retval = send(connected_fd, buf, 103425, 0);
    if (retval == -1) {
        perror("Father: send error");
    } else
        printf("Father: send %d bytes\n", retval);

    return 0;
}


阅读(4010) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~