关于 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
呼叫。这确保只有已被接受的客户端才能继续其代码路径。
我在 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
呼叫。这确保只有已被接受的客户端才能继续其代码路径。