socket 编程非阻塞客户端服务端sylixos

connect参考
服务端参考

针对 sylixos 应用手册中 15.5 AF_UNIX 域协议
UNIX 域套接字是一种高级的IPC 机制,这种形式的IPC 可以在同一计算机系统上运行的两个进程之间进行通信。虽然因特网域套接字可用于同一目的,但UNIX 域套接字的效率更高。UNIX 域套接字仅仅复制数据,并不执行协议处理,因此,无需添加或者删除网络报头,无需计算校验和,无需产生序列号,无需发送确认报文等。

本次针对非阻塞方式

服务端

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <sys/un.h>
#include <unistd.h>
#include <string.h>

#define AF_UNIX_FILE "afunix.tmp"


int main (int argc, char **argv)
{
    printf("Hello SylixOS!\n");

    int ssockfd, csockfd;
    socklen_t slen, clen;
    struct sockaddr_un saddr;
    int i, bytes;
    char str[16];
    unlink(AF_UNIX_FILE);
    ssockfd = socket(AF_UNIX, SOCK_STREAM, 0);
    if (ssockfd < 0) {
        fprintf(stderr, "[server]socket error.\n");
        return (-1);
    }

    slen = sizeof(saddr);
    strcpy(saddr.sun_path, AF_UNIX_FILE);
    saddr.sun_family = AF_UNIX;


#if 1
    int opt = fcntl(ssockfd, F_GETFL, 0);
    printf("F_GETFL:0x%x\n",opt);
    if (opt == -1) {
        printf("fcntl getfl fail. errno=%d\n", errno);
//        return false;
    }
    int ret;
    if (0)
        ret = fcntl(ssockfd, F_SETFL, opt & ~O_NONBLOCK);
    else
        ret = fcntl(ssockfd, F_SETFL, opt | O_NONBLOCK);
    if (ret == -1) {
        printf("fcntl setfl fail. errno=%d\n", errno);
//        return false;
    }
//    return true;
#endif


    bind(ssockfd, (struct sockaddr *) &saddr, slen);
    listen(ssockfd, 5);


    fprintf(stdout, "[server]waiting for client connect...\n");


ACCEPT:
    csockfd = accept(ssockfd, (struct sockaddr *) &saddr, &clen);
    if (csockfd < 0) {

        if(errno == EAGAIN)
            goto ACCEPT;


        fprintf(stderr, "[server]%d: %s.\n",errno,strerror(errno));
        perror("server:");

        fprintf(stderr, "[server]accept error.\n");
        close(ssockfd);
        return (-1);
    }
    fprintf(stdout, "[server]connect success.\n");
    for (i = 0; i < 500; i++) {
        bytes = read(csockfd, str, 16);
        if (bytes < 0) {

            if(ECONNRESET == errno)
                goto ACCEPT;

            fprintf(stderr, "[server]%d: %s.\n",errno,strerror(errno));
            perror("Error:");

            fprintf(stderr, "[server]read error.\n");
//            break;
        }

        if (strncmp("client", str, 6) == 0) {
            fprintf(stdout, "[server]receiver from client is: %s\n", str);
        } else {

            fprintf(stderr, "[server]client send failed.\n");
            break;
        }
        sleep(1);
        fprintf(stdout, "[server]server reply ACK.\n");
        bytes = write(csockfd, "ACK", 4);
        if (bytes < 0) {


            if(ECONNRESET == errno)
                goto ACCEPT;

            fprintf(stderr, "[server]%d: %s.\n",errno,strerror(errno));
            perror("Error:");
            fprintf(stderr, "[server]write error.\n");
//            break;
        }
        fprintf(stderr, "[server]%d\n", i);
    }
    unlink(AF_UNIX_FILE);
    close(csockfd);
    close(ssockfd);

    return  (0);
}


客户端

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <sys/un.h>
#include <unistd.h>

#define AF_UNIX_FILE "afunix.tmp"


int main (int argc, char **argv)
{
    printf("Hello SylixOS!\n");


    fd_set fdr, fdw;
    struct timeval timeout;
    int err = 0;
    int errlen = sizeof(err);

    int sockfd;
    struct sockaddr_un addr;
    socklen_t len;
    int i, bytes, result;
    char str[16];
    sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
    if (sockfd < 0) {
        fprintf(stderr, "[client]socket error.\n");

        return (-1);
    }

#if 1
    int opt = fcntl(sockfd, F_GETFL, 0);
    printf("F_GETFL:0x%x\n",opt);
    if (opt == -1) {
        printf("fcntl getfl fail. errno=%d\n", errno);
//        return false;
    }
    int ret;
    if (0)
        ret = fcntl(sockfd, F_SETFL, opt & ~O_NONBLOCK);
    else
        ret = fcntl(sockfd, F_SETFL, opt | O_NONBLOCK);
    if (ret == -1) {
        printf("fcntl setfl fail. errno=%d\n", errno);
//        return false;
    }
//    return true;
#endif

    bzero(&addr, sizeof(addr));
    len = sizeof(addr);
    addr.sun_family = AF_UNIX;
    strcpy(addr.sun_path, AF_UNIX_FILE);

    result = connect(sockfd, (struct sockaddr *) &addr, len);
    if (result < 0) {
        fprintf(stderr, "[client]connect error.\n");
        fprintf(stderr, "[client]%d: %s.\n",errno,strerror(errno));

        if (errno == EINPROGRESS) {
              printf("Doing connection.\n");
              /*正在处理连接*/
              FD_ZERO(&fdr);
              FD_ZERO(&fdw);
              FD_SET(sockfd, &fdr);
              FD_SET(sockfd, &fdw);
              timeout.tv_sec = 10;
              timeout.tv_usec = 0;
              ret = select(sockfd + 1, &fdr, &fdw, NULL, &timeout);
              printf("ret is: %d\n", ret);
              /*select调用失败*/
              if (ret < 0) {
                fprintf(stderr, "connect error:%s\n", strerror(errno));
                close(sockfd);
                return -1;
              }

              /*连接超时*/
              if (ret == 0) {
                fprintf(stderr, "Connect timeout.\n");
                close(sockfd);
                return -1;
              }
              /*[1] 当连接成功建立时,描述符变成可写,rc=1*/
              if (ret == 1 && FD_ISSET(sockfd, &fdw)) {
                printf("Connect success\n");


                for (i = 0; i < 10; i++) {
                    bytes = write(sockfd, "client", 7);
                    if (bytes < 0) {
                        fprintf(stderr, "[client]write error.\n");
                        break;
                    }
                    sleep(2);
                    bytes = read(sockfd, str, 16);
                    if (bytes < 0) {
                        fprintf(stderr, "[client]read error.\n");
            //            break;
                    }
                    fprintf(stdout, "[client]receive ACK from server.\n");
                }

                close(sockfd);
                return 0;
              }
              /*[2] 当连接建立遇到错误时,描述符变为即可读,也可写,rc=2 遇到这种情况,可调用getsockopt函数*/
              if (ret == 2) {
                if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) {
                  fprintf(stderr, "getsockopt(SO_ERROR): %s", strerror(errno));
                  close(sockfd);
                  return -1;

                }

                if (err) {
                  errno = err;
                  fprintf(stderr, "connect error:%s\n", strerror(errno));
                  close(sockfd);
                  return -1;

                }
              }

            }

        fprintf(stderr, "[client]connect error.\n");
        close(sockfd);
//        return (-1);
    }
    fprintf(stdout, "[client]connect server success.\n");

    close(sockfd);


    return  (0);
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值