关于C(Linux)中socket服务器客户端编程中accept()的问题
我在Linux中用C语言编写了一个服务器和客户端程序 代码如下: 服务器代码:关于C(Linux)中socket服务器客户端编程中accept()的问题,c,linux,sockets,network-programming,client-server,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 soc
#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;
}
客户端输出:
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;
}
我不希望客户端连接,直到服务器调用accept()与客户端连接
运气不好,TCP不是这样工作的listen(socket_desc,3)
创建一个待办事项队列,使用第二个参数作为其长度的提示,在本例中,该参数将被忽略,因为它太小。此队列的目的是保存TCP已完成但服务器应用程序尚未接受的连接。根据平台的不同,典型尺寸从50到500或更多不等
我只想让客户端等待或超时,直到服务器调用accept()
在它们之间建立连接
不可实现的。你为什么认为你需要这个
我不知道为什么会发生这种情况以及如何解决它
您无法解决它,除非按照@IshayPeled的回答通过无意义的额外发送/接收。这不是一个需要解决的问题。如果你不这么认为,请告诉我们原因。其他所有编写的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;
}
#包括//printf
#包括//strlen
#包含//套接字
#包括//inet\u addr
int main(int argc,char*argv[])
{
char-buf[1];
int袜子;
服务器中的结构sockaddr_;
字符消息[1000],服务器回复[2000];
int ret;
//创建套接字
sock=socket(AF\u INET,sock\u STREAM,0);
如果(sock==-1)
{
printf(“无法创建套接字”);
}
放置(“已创建套接字”);
server.sin_addr.s_addr=inet_addr(“127.0.0.1”);
server.sinu family=AF\u INET;
server.sin_port=htons(8888);
//连接到远程服务器
ret=connect(sock,(struct sockaddr*)&server,sizeof(server));
如果(ret<0)
{
perror(“连接失败。错误”);
返回1;
}
recv(短袜、布袋、1号、味精等一份);
放置(“已连接”);
关闭(袜子);
而(1),;
返回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;
}
#包括
#包括//strlen
#包括
#包括//inet\u addr
#包括//写入
int main(int argc,char*argv[])
{
int socket_desc,client_sock,c,read_size;
服务器、客户端中的结构sockaddr_;
char client_message[2000];
//创建套接字
socket\u desc=socket(AF\u INET,SOCK\u STREAM,0);
如果(套接字描述==-1)
{
printf(“无法创建套接字”);
}
放置(“已创建套接字”);
//在结构中准备sockaddr_
server.sinu family=AF\u INET;
server.sin\u addr.s\u addr=INADDR\u ANY;
server.sin_port=htons(8888);
//束缚
if(绑定(socket_desc,(struct sockaddr*)&server,sizeof(server))<0
{
//打印错误消息
perror(“绑定失败。错误”);
返回1;
}
看跌期权(“绑定完成”);
//听
听(插座描述,3);
//接受和传入连接
puts(“等待传入连接…”);
c=sizeof(结构sockaddr_in);
//接受来自传入客户端的连接
client\u sock=accept(socket\u desc,(struct sockaddr*)和client,(socklen\u t*)和c);
发送(客户端_sock,“1”,1,0);
如果(客户_sock<0)
{
perror(“接受失败”);
返回1;
}
看跌期权(“已接受连接”);
关闭(客户端_sock);
puts(“我在While循环”);
而(1)
{
}
返回0;
}
在客户端:我在客户端添加了一个
recv
调用,该调用会一直阻塞,直到服务器实际发送某些内容为止
在服务器端:我在accept呼叫之后添加了一个
send
呼叫。这确保只有已被接受的客户端才能继续其代码路径。您的服务器接受第一个连接,然后无限循环一段时间(1)。你必须断开代码连接并进入循环。伙计们,运行他的代码。即使服务器在while循环中并且不接受任何东西,客户端代码中的connect部分也不会失败(我测试了它运行多个并行的客户端实例)。@alk您显然从未听说过listen backlog队列。@EJP:的确,我错过了队列中可能已完成的传入连接。如果您想等待,只需编写等待的代码。如果客户机需要知道服务器什么时候做了什么,那么服务器需要告诉客户机什么时候做了什么。我已经给出了backlog queue 100,但是结果是一样的。当然,结果是一样的,只是100个客户机可以做第二个客户机做的事情。我不明白你为什么认为它会改变。如果你想阻止它,你可以在调用connect之后在客户端调用recv,并在服务器端调用accept之后立即发送内容。recv调用将被阻止,因为没有数据到达该套接字,并且只有在服务器发送某个数据后才会释放(这发生在accept之后)。您能给出为什么客户端在未调用accept时接受与服务器的连接吗?@IshayPeled我运行这些代码不仅仅是为了开始使用套接字,我有一个完整的应用程序,其中我解决了这个问题为什么MSG\u WAITFORONE
?有没有证据表明他想在事后进入非阻塞模式?@EJP你显然对这个问题非常了解,我在阅读你的答案和评论时学到了很多,请提供一个更好的答案,而不是抨击我的答案。用一种非被动的攻击性的方式来处理你的评论——这是我能想出的最快的例子,它实际上解决了他的问题,我不知道他的应用的全部范围,所以我不能确定
root@beaglebone:/home/Saad/test# ./client_test_1
Socket created
1Connected
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("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;
}