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

时间:2015-05-11 05:55:08

标签: c linux sockets network-programming client-server

我在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

2 个答案:

答案 0 :(得分:3)

@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电话。这确保只有已被接受的客户端才会继续其代码路径。

答案 1 :(得分:1)

  

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

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

  

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

不可实现的。为什么你认为你需要这个?

  

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

根据@ IshayPeled的回答,除了无意义的额外发送/接收之外你无法解决它。这不是一个需要解决的问题。如果您不这么认为,请告诉我们原因。所有其他TCP应用程序都是以这种方式编写的。你的有什么不同?