关于 C 套接字服务器客户端编程中 accept() 的问题 (Linux)

Issue regarding accept() in socket server client programming in C (Linux)

我在 Linux.

中使用 C 中的套接字编写了服务器和客户端程序

代码如下:

服务器代码:

#include<stdio.h>
#include<string.h>    //strlen
#include<sys/socket.h>
#include<arpa/inet.h> //inet_addr
#include<unistd.h>    //write

int main(int argc , char *argv[])
{
int socket_desc , client_sock , c , read_size;
struct sockaddr_in server , client;
char client_message[2000];

//Create socket
socket_desc = socket(AF_INET , SOCK_STREAM , 0);
if (socket_desc == -1)
{
    printf("Could not create socket");
}
puts("Socket created");

//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons( 8888 );

//Bind
if( bind(socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0)
{
    //print the error message
    perror("bind failed. Error");
    return 1;
}
puts("bind done");

//Listen
listen(socket_desc , 3);

//Accept and incoming connection
puts("Waiting for incoming connections...");
c = sizeof(struct sockaddr_in);

//accept connection from an incoming client
client_sock = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c);
if (client_sock < 0)
{
    perror("accept failed");
    return 1;
 }
puts("Connection accepted");
  close(client_sock);
  puts("I am at While loop");
  while(1)
    {
    }
return 0;
}

客户代码:

#include<stdio.h> //printf
#include<string.h>    //strlen
#include<sys/socket.h>    //socket
#include<arpa/inet.h> //inet_addr

int main(int argc , char *argv[])
{
int sock;
struct sockaddr_in server;
char message[1000] , server_reply[2000];

//Create socket
sock = socket(AF_INET , SOCK_STREAM , 0);
if (sock == -1)
{
    printf("Could not create socket");
}
puts("Socket created");

server.sin_addr.s_addr = inet_addr("127.0.0.1");
server.sin_family = AF_INET;
server.sin_port = htons( 8888 );

//Connect to remote server
if (connect(sock , (struct sockaddr *)&server , sizeof(server)) < 0)
{
    perror("connect failed. Error");
    return 1;
}

puts("Connected\n");
close(sock);
while(1);
return 0;
}

当我 运行 服务器代码然后客户端代码它工作正常但是当我终止客户端代码 运行 它再次(服务器代码只执行一次)它自动连接到服务器而不接受被调用按服务器。

在服务器调用 accept() 连接客户端之前,我不希望客户端连接。

我只是想让客户端等待或超时,直到服务器调用 accept() 来建立它们之间的连接。

我得到的输出如下:

服务器输出:

root@beaglebone:/home/Saad/test# ./server_test
Socket created                                                      
bind done                              
Waiting for incoming connections...
Connection accepted
I am at While loop

客户端输出:

root@beaglebone:/home/Saad/test# ./client_test     
Socket created                         
Connected                                                           

^C                                                   
root@beaglebone:/home/Saad/test# ./client_test
Socket created                                              
Connected          

我不知道为什么会这样,也不知道如何解决。

更新:

我在客户端代码中进行了一些编辑后尝试了下面的答案,但我遇到了同样的问题。

客户代码:

#include<stdio.h> //printf
#include<string.h>    //strlen
#include<sys/socket.h>    //socket
#include<arpa/inet.h> //inet_addr

int main(int argc , char *argv[])
{
   char buf[1];
int sock;
struct sockaddr_in server;
char message[1000] , server_reply[2000];
int ret;

//Create socket
sock = socket(AF_INET , SOCK_STREAM , 0);
if (sock == -1)
{
    printf("Could not create socket");
}
puts("Socket created");

server.sin_addr.s_addr = inet_addr("192.168.1.2");
server.sin_family = AF_INET;
server.sin_port = htons( 8888 );

//Connect to remote server
ret = connect(sock , (struct sockaddr *)&server , sizeof(server));
if (ret < 0)
{
    perror("connect failed. Error");
    return 1;
}
recv(sock, buf, 1, MSG_WAITFORONE);
printf("%s",buf);
puts("Connected\n");
close(sock);
sock = socket(AF_INET , SOCK_STREAM , 0);
if (sock == -1)
{
    printf("Could not create socket");
}
puts("Socket created");
ret = connect(sock , (struct sockaddr *)&server , sizeof(server));
if (ret < 0)
{
    perror("connect failed. Error");
    return 1;
}
else
{
 puts("Connected\n");
}
while(1);
return 0;
}

客户端输出:

root@beaglebone:/home/Saad/test# ./client_test_1
Socket created
1Connected

Socket created
Connected

I don't want client to get connected until server calls accept() to connect with client.

运气不好,TCP 不是这样工作的。 listen(socket_desc , 3) 创建一个 积压队列 ,使用第二个参数作为其长度的提示,在这种情况下将被忽略,因为它太小了。此队列的目的是保存已由 TCP 完成但尚未被服务器应用程序接受的连接。典型大小从 50 到 500 或更多不等,具体取决于平台。

I just want client to wait or give some timeout until server calls accept() to establish connection between them.

无法实现。为什么你认为你需要这个?

I don't know why this is happening and how to resolve it.

你无法解决它,除非按照@IshayPeled 的回答进行毫无意义的额外 send/recv。这不是一个需要解决的问题。如果您不这么认为,请告诉我们原因。曾经编写的所有其他 TCP 应用程序都以这种方式工作。你的有什么不同?

@EJP 解释的很好,如果你想解决你的问题,使用这个代码:

客户:

#include<stdio.h> //printf
#include<string.h>    //strlen
#include<sys/socket.h>    //socket
#include<arpa/inet.h> //inet_addr

int main(int argc , char *argv[])
{
    char buf[1];
    int sock;
    struct sockaddr_in server;
    char message[1000] , server_reply[2000];
    int ret;

    //Create socket
    sock = socket(AF_INET , SOCK_STREAM , 0);
    if (sock == -1)
    {
        printf("Could not create socket");
    }
    puts("Socket created");

    server.sin_addr.s_addr = inet_addr("127.0.0.1");
    server.sin_family = AF_INET;
    server.sin_port = htons( 8888 );

    //Connect to remote server
    ret = connect(sock , (struct sockaddr *)&server , sizeof(server));
    if (ret < 0)
    {
        perror("connect failed. Error");
        return 1;
    }
    recv(sock, buf, 1, MSG_WAITFORONE);

    puts("Connected\n");
    close(sock);
    while(1);
    return 0;
}

服务器:

#include<stdio.h>
#include<string.h>    //strlen
#include<sys/socket.h>
#include<arpa/inet.h> //inet_addr
#include<unistd.h>    //write   
int main(int argc , char *argv[])
{   
    int socket_desc , client_sock , c , read_size;
    struct sockaddr_in server , client;
    char client_message[2000];

    //Create socket
    socket_desc = socket(AF_INET , SOCK_STREAM , 0);
    if (socket_desc == -1)
    {
        printf("Could not create socket");
    }
    puts("Socket created");

    //Prepare the sockaddr_in structure
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = INADDR_ANY;
    server.sin_port = htons( 8888 );

    //Bind
    if( bind(socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0)
    {
        //print the error message
        perror("bind failed. Error");
        return 1;
    }
    puts("bind done");

    //Listen
    listen(socket_desc , 3);

    //Accept and incoming connection
    puts("Waiting for incoming connections...");
    c = sizeof(struct sockaddr_in);

    //accept connection from an incoming client
    client_sock = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c);

    send(client_sock, "1", 1, 0);
    if (client_sock < 0)
    {
        perror("accept failed");
        return 1;
    }
    puts("Connection accepted");
    close(client_sock);
    puts("I am at While loop");
    while(1)
    {
    }
    return 0;
}

在客户端:
我在客户端添加了一个 recv 调用,它会阻塞直到服务器实际发送一些东西。

在服务器端:
我在接受呼叫后立即添加了一个 send 呼叫。这确保只有已被接受的客户端才能继续其代码路径。