Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 仅使用插座实现单个工艺管道_C_Sockets_Pipe_Freebsd - Fatal编程技术网

C 仅使用插座实现单个工艺管道

C 仅使用插座实现单个工艺管道,c,sockets,pipe,freebsd,C,Sockets,Pipe,Freebsd,我想为单个进程实现一个非阻塞套接字,但我也没有,但我可以使用非阻塞套接字。以下是我现在拥有的: #include <stdint.h> #include <stdio.h> #include <fcntl.h> #include <string.h> #include <arpa/inet.h> int main(void) { // Wannabe server struct sockaddr_in addr;

我想为单个进程实现一个非阻塞套接字,但我也没有,但我可以使用非阻塞套接字。以下是我现在拥有的:

#include <stdint.h>
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <arpa/inet.h>

int main(void)
{
    // Wannabe server
    struct sockaddr_in addr;
    int fd;

    fd = socket(AF_INET, SOCK_STREAM, 0);
    if(fd == -1)
    {
        printf("Error opening socket\n");
        return -1;
    }

    addr.sin_port = htons(0);
    addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    addr.sin_family = AF_INET;

    if(bind(fd, (struct sockaddr *)&addr,sizeof(struct sockaddr_in) ) == -1)
    {
        printf("Error binding socket\n");
        return -1;
    }

    if (fcntl(fd, F_SETFL, O_NONBLOCK))
    {
        printf("Unable to make socket non-blocking");
        return -1;
    }


    socklen_t socklen = sizeof(addr);
    getsockname(fd, &addr, &socklen);

    const uint16_t port = ntohs(addr.sin_port);
    printf("Successfully bound to port %u\n", ntohs(addr.sin_port));

    // Accept the data packet from client and verification
    struct sockaddr_in cli;
    size_t cli_size = sizeof(cli);

    accept(fd, &cli, &cli_size);



    // Wannabe client
    int sockfd;
    struct sockaddr_in servaddr;

    // socket create and varification
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1) {
        printf("socket creation failed...\n");
        return -1;
    }
    else
        printf("Socket successfully created..\n");
    memset(&servaddr, 0, sizeof(servaddr));

    // assign IP, PORT
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
    servaddr.sin_port = addr.sin_port;

    // connect the client socket to server socket
    if (connect(sockfd, &servaddr, sizeof(servaddr)) != 0)
        printf("connection with the server failed...\n");
    else
        printf("connected to the server..\n");

    return 0;
}

我一定是客户端套接字出错了,或者accept调用可能有问题。操作系统很奇怪,但它是FreeBSD fork,根本不支持进程调用。任何帮助都将不胜感激

OPs发布的代码编译不干净

编译时,始终启用警告,然后修复这些警告

以下是编译器的输出:

gcc    -ggdb -Wall -Wextra -Wconversion -pedantic -std=gnu11  -c "untitled.c"  
untitled.c: In function ‘main’:
untitled.c:38:21: warning: passing argument 2 of ‘getsockname’ from incompatible pointer type [-Wincompatible-pointer-types]
     getsockname(fd, &addr, &socklen);
                     ^
In file included from /usr/include/netinet/in.h:23:0,
                 from /usr/include/arpa/inet.h:22,
                 from untitled.c:5:
/usr/include/x86_64-linux-gnu/sys/socket.h:116:12: note: expected ‘struct sockaddr * restrict’ but argument is of type ‘struct sockaddr_in *’
 extern int getsockname (int __fd, __SOCKADDR_ARG __addr,
            ^~~~~~~~~~~
untitled.c:47:16: warning: passing argument 2 of ‘accept’ from incompatible pointer type [-Wincompatible-pointer-types]
     accept(fd, &cli, &cli_size);
                ^
In file included from /usr/include/netinet/in.h:23:0,
                 from /usr/include/arpa/inet.h:22,
                 from untitled.c:5:
/usr/include/x86_64-linux-gnu/sys/socket.h:232:12: note: expected ‘struct sockaddr * restrict’ but argument is of type ‘struct sockaddr_in *’
 extern int accept (int __fd, __SOCKADDR_ARG __addr,
            ^~~~~~
untitled.c:47:22: warning: passing argument 3 of ‘accept’ from incompatible pointer type [-Wincompatible-pointer-types]
     accept(fd, &cli, &cli_size);
                      ^
In file included from /usr/include/netinet/in.h:23:0,
                 from /usr/include/arpa/inet.h:22,
                 from untitled.c:5:
/usr/include/x86_64-linux-gnu/sys/socket.h:232:12: note: expected ‘socklen_t * restrict {aka unsigned int * restrict}’ but argument is of type ‘size_t * {aka long unsigned int *}’
 extern int accept (int __fd, __SOCKADDR_ARG __addr,
            ^~~~~~
untitled.c:71:25: warning: passing argument 2 of ‘connect’ from incompatible pointer type [-Wincompatible-pointer-types]
     if (connect(sockfd, &servaddr, sizeof(servaddr)) != 0)
                         ^
In file included from /usr/include/netinet/in.h:23:0,
                 from /usr/include/arpa/inet.h:22,
                 from untitled.c:5:
/usr/include/x86_64-linux-gnu/sys/socket.h:126:12: note: expected ‘const struct sockaddr *’ but argument is of type ‘struct sockaddr_in *’
 extern int connect (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len);
            ^~~~~~~
untitled.c:40:20: warning: unused variable ‘port’ [-Wunused-variable]
     const uint16_t port = ntohs(addr.sin_port);
                    ^~~~
Compilation finished successfully.
虽然最后一条编译器消息说“编译成功完成”,但实际情况是编译器输出了一些针对每个警告的“变通方法”。这并不意味着编译器生成了正确的代码

请修复所有警告,然后对您的问题进行编辑


建议阅读
connect()
accept()
getsockname()
的手册页。这可能会帮助您取得一些进展……我已经在非阻塞模式下管理了socket/listen/accept+socket/connect内容。我让数据朝一个方向流动(服务器到客户端),但显然不是客户端到服务器(我希望FD5变得可读,但显然不是)。需要做更多的工作

#include <stdint.h>
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <errno.h>
#include <unistd.h>

int
main( int argc, char **argv )
{
    // Wannabe server
    struct sockaddr_in addr;
    int fd;

    if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        fprintf( stderr, "Error opening socket 1: %s\n", strerror( errno ) );
        return errno;
    }

    addr.sin_port = htons(0);
    addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    addr.sin_family = AF_INET;

    if (bind(fd, (struct sockaddr *)&addr,sizeof(struct sockaddr_in) ) == -1) {
        fprintf( stderr, "Error binding socket 1: %s\n", strerror( errno ) );
        return errno;
    }

    if (fcntl(fd, F_SETFL, O_NONBLOCK)) {
        fprintf( stderr, "Error setting NONBLOCK socket 1: %s\n", strerror( errno ) );
        return errno;
    }

    if (listen( fd, 5 )) {
        fprintf( stderr, "Error listening socket 1: %s\n", strerror( errno ) );
        return errno;
    }

    socklen_t socklen = sizeof(addr);
    getsockname(fd, (struct sockaddr *)&addr, &socklen);

    const uint16_t port = ntohs(addr.sin_port);
    printf( "Successfully bound to port %u\n", ntohs(addr.sin_port));

    struct sockaddr_in cli;
    socklen_t cli_size = sizeof(cli);

    errno = 0;

    int result;

    int srv2cli = accept( fd, (struct sockaddr *)&cli, &cli_size );

    printf( "Non-blocking accept() returns %d: %s\n", srv2cli, strerror( errno ) );


    // Wannabe client
    int sockfd;
    struct sockaddr_in servaddr;

    // socket create and varification
    if ((sockfd = socket( AF_INET, SOCK_STREAM, 0 )) == -1) {
        fprintf( stderr, "Error opening socket 2: %s\n", strerror( errno ) );
        return errno;
    }

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

    // assign IP, PORT
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
    servaddr.sin_port = addr.sin_port;

    if (fcntl( sockfd, F_SETFL, O_NONBLOCK)) {
        fprintf( stderr, "Error setting NONBLOCK socket 2: %s\n", strerror( errno ) );
        return errno;
    }

    errno = 0;
    result = connect( sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr) );

    printf( "Non-blocking connect() returns %d: %s\n", result, strerror( errno ) );

    for ( ; ; ) {
        fd_set  readfds;
        fd_set  writefds;
        fd_set  exceptfds;
        struct timeval   tv;

        int maxfd = fd;

        if (maxfd < sockfd) maxfd = sockfd;
        if (maxfd < srv2cli) maxfd = srv2cli;

        FD_ZERO( &readfds );
        FD_ZERO( &writefds );
        FD_ZERO( &exceptfds );

        FD_SET( fd, &readfds );
        FD_SET( fd, &writefds );
        FD_SET( fd, &exceptfds );

        FD_SET( sockfd, &readfds );
        FD_SET( sockfd, &writefds );
        FD_SET( sockfd, &exceptfds );

        if (srv2cli >= 0) {
            FD_SET( srv2cli, &readfds );
            FD_SET( srv2cli, &writefds );
            FD_SET( srv2cli, &exceptfds );
        }

        tv.tv_sec = 5;
        tv.tv_usec = 0;

        errno = 0;
        result = select( maxfd, &readfds, &writefds, &exceptfds, &tv );

        printf( "select returns %d : %s\n", result, strerror( errno ) );

        if (FD_ISSET( fd, &readfds )) {
            printf( "fd (%d) is ready to read (execute accept())\n", fd );
            srv2cli = accept( fd, (struct sockaddr *)&cli, &cli_size );
            printf( "\"Server\" accepted connection on fd %d (%s)\n", srv2cli, strerror( errno ) );
            if (fcntl( srv2cli, F_SETFL, O_NONBLOCK)) {
                fprintf( stderr, "Error setting NONBLOCK srv2cli socket : %s\n", strerror( errno ) );
                return errno;
            }
            result = write( srv2cli, "Hello, world", 12 );
            printf( "Transmitted %d bytes to client\n", result );
        }
        if (FD_ISSET( fd, &writefds )) printf( "fd (%d) is ready to write\n", fd );
        if (FD_ISSET( fd, &exceptfds )) printf( "fd (%d) is ready to except\n", fd );

        if (FD_ISSET( sockfd, &readfds )) {
            char buf[32];
            result = read( sockfd, buf, sizeof(buf) );
            printf( "sockfd(%d) is ready to read...got %d bytes\n", sockfd, result );
        }
        if (FD_ISSET( sockfd, &writefds )) {
            result = write( sockfd, "Foobar", 6 );
            printf( "sockfd (%d) is ready to write...sent %d bytes\n", sockfd, result );
        }
        if (FD_ISSET( sockfd, &exceptfds )) printf( "sockfd (%d) is ready to except\n", sockfd );

        if (FD_ISSET( srv2cli, &readfds )) printf( "srv2cli (%d) is ready to read\n", srv2cli );
        if (FD_ISSET( srv2cli, &writefds )) printf( "srv2cli (%d) is ready to write\n", srv2cli );
        if (FD_ISSET( srv2cli, &exceptfds )) printf( "srv2cli (%d) is ready to except\n", srv2cli );
    }

    return 0;
}

(没有停止条件,所以你需要杀死它!)

你的操作系统有
错误吗?如果没有,那就太过分了。如果是这样,你应该更好地利用它。请参见
perror
@rici我确信它有!很抱歉没有出现这种情况:
connect
上的错误显示“连接被拒绝”,我已经升级了,因为尽管我开发了多个服务器端或客户端应用程序,但我从未见过它们具有相同的功能。然后:1)在哪里是
listen()
?2) 是我错了还是客户端的connect()只有在服务器接受后才成功?@Cubo78谢谢你的关注,好像我错过了!我将尝试修复此问题并更新此问题。我怀疑这里的挑战是从同一线程执行
connect()
accept()
。这些都是阻塞调用,除非你设置了NONBLOCK,所以一旦你做了一个,你就不能做另一个。(如果这是一个家庭作业问题,这可能是练习的重点。)我想你可以通过在两个插座上都设置NONBLOCK,然后同时执行
connect
accept
,最后使用
select
在各个插座准备就绪时继续操作。
#include <stdint.h>
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <errno.h>
#include <unistd.h>

int
main( int argc, char **argv )
{
    // Wannabe server
    struct sockaddr_in addr;
    int fd;

    if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        fprintf( stderr, "Error opening socket 1: %s\n", strerror( errno ) );
        return errno;
    }

    addr.sin_port = htons(0);
    addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    addr.sin_family = AF_INET;

    if (bind(fd, (struct sockaddr *)&addr,sizeof(struct sockaddr_in) ) == -1) {
        fprintf( stderr, "Error binding socket 1: %s\n", strerror( errno ) );
        return errno;
    }

    if (fcntl(fd, F_SETFL, O_NONBLOCK)) {
        fprintf( stderr, "Error setting NONBLOCK socket 1: %s\n", strerror( errno ) );
        return errno;
    }

    if (listen( fd, 5 )) {
        fprintf( stderr, "Error listening socket 1: %s\n", strerror( errno ) );
        return errno;
    }

    socklen_t socklen = sizeof(addr);
    getsockname(fd, (struct sockaddr *)&addr, &socklen);

    const uint16_t port = ntohs(addr.sin_port);
    printf( "Successfully bound to port %u\n", ntohs(addr.sin_port));

    struct sockaddr_in cli;
    socklen_t cli_size = sizeof(cli);

    errno = 0;

    int result;

    int srv2cli = accept( fd, (struct sockaddr *)&cli, &cli_size );

    printf( "Non-blocking accept() returns %d: %s\n", srv2cli, strerror( errno ) );


    // Wannabe client
    int sockfd;
    struct sockaddr_in servaddr;

    // socket create and varification
    if ((sockfd = socket( AF_INET, SOCK_STREAM, 0 )) == -1) {
        fprintf( stderr, "Error opening socket 2: %s\n", strerror( errno ) );
        return errno;
    }

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

    // assign IP, PORT
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
    servaddr.sin_port = addr.sin_port;

    if (fcntl( sockfd, F_SETFL, O_NONBLOCK)) {
        fprintf( stderr, "Error setting NONBLOCK socket 2: %s\n", strerror( errno ) );
        return errno;
    }

    errno = 0;
    result = connect( sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr) );

    printf( "Non-blocking connect() returns %d: %s\n", result, strerror( errno ) );

    for ( ; ; ) {
        fd_set  readfds;
        fd_set  writefds;
        fd_set  exceptfds;
        struct timeval   tv;

        int maxfd = fd;

        if (maxfd < sockfd) maxfd = sockfd;
        if (maxfd < srv2cli) maxfd = srv2cli;

        FD_ZERO( &readfds );
        FD_ZERO( &writefds );
        FD_ZERO( &exceptfds );

        FD_SET( fd, &readfds );
        FD_SET( fd, &writefds );
        FD_SET( fd, &exceptfds );

        FD_SET( sockfd, &readfds );
        FD_SET( sockfd, &writefds );
        FD_SET( sockfd, &exceptfds );

        if (srv2cli >= 0) {
            FD_SET( srv2cli, &readfds );
            FD_SET( srv2cli, &writefds );
            FD_SET( srv2cli, &exceptfds );
        }

        tv.tv_sec = 5;
        tv.tv_usec = 0;

        errno = 0;
        result = select( maxfd, &readfds, &writefds, &exceptfds, &tv );

        printf( "select returns %d : %s\n", result, strerror( errno ) );

        if (FD_ISSET( fd, &readfds )) {
            printf( "fd (%d) is ready to read (execute accept())\n", fd );
            srv2cli = accept( fd, (struct sockaddr *)&cli, &cli_size );
            printf( "\"Server\" accepted connection on fd %d (%s)\n", srv2cli, strerror( errno ) );
            if (fcntl( srv2cli, F_SETFL, O_NONBLOCK)) {
                fprintf( stderr, "Error setting NONBLOCK srv2cli socket : %s\n", strerror( errno ) );
                return errno;
            }
            result = write( srv2cli, "Hello, world", 12 );
            printf( "Transmitted %d bytes to client\n", result );
        }
        if (FD_ISSET( fd, &writefds )) printf( "fd (%d) is ready to write\n", fd );
        if (FD_ISSET( fd, &exceptfds )) printf( "fd (%d) is ready to except\n", fd );

        if (FD_ISSET( sockfd, &readfds )) {
            char buf[32];
            result = read( sockfd, buf, sizeof(buf) );
            printf( "sockfd(%d) is ready to read...got %d bytes\n", sockfd, result );
        }
        if (FD_ISSET( sockfd, &writefds )) {
            result = write( sockfd, "Foobar", 6 );
            printf( "sockfd (%d) is ready to write...sent %d bytes\n", sockfd, result );
        }
        if (FD_ISSET( sockfd, &exceptfds )) printf( "sockfd (%d) is ready to except\n", sockfd );

        if (FD_ISSET( srv2cli, &readfds )) printf( "srv2cli (%d) is ready to read\n", srv2cli );
        if (FD_ISSET( srv2cli, &writefds )) printf( "srv2cli (%d) is ready to write\n", srv2cli );
        if (FD_ISSET( srv2cli, &exceptfds )) printf( "srv2cli (%d) is ready to except\n", srv2cli );
    }

    return 0;
}
dhm@rubidium-debian:~/code/nettest$ ./a.out 2>&1 | head -20
Successfully bound to port 60219
Non-blocking accept() returns -1: Resource temporarily unavailable
Non-blocking connect() returns -1: Operation now in progress
select returns 1 : Success
fd (3) is ready to read (execute accept())
"Server" accepted connection on fd 5 (Success)
Transmitted 12 bytes to client
select returns 2 : Success
sockfd(4) is ready to read...got 12 bytes
sockfd (4) is ready to write...sent 6 bytes
select returns 1 : Success
sockfd (4) is ready to write...sent 6 bytes
select returns 1 : Success
sockfd (4) is ready to write...sent 6 bytes
select returns 1 : Success
sockfd (4) is ready to write...sent 6 bytes
select returns 1 : Success
sockfd (4) is ready to write...sent 6 bytes
select returns 1 : Success
sockfd (4) is ready to write...sent 6 bytes