有人可以帮助确定我的服务器无法接受来自客户端的多条消息的原因吗?
我试图让流程如下:
1.客户端向服务器发送消息大小
2.服务器接收大小并发回响应。在这种情况下0.
3.客户端检查响应,然后将消息写入服务器。
4.服务器读取消息并将其打印出来。
我遇到的问题是第4步的accept()永远不会解锁。
客户端
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
int main(int argc, char *argv[])
{
int sock = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in s_address;
s_address.sin_family = AF_INET;
s_address.sin_port = htons(51717);
s_address.sin_addr.s_addr = INADDR_ANY;
if (connect(sock, (struct sockaddr *) &s_address, sizeof(s_address)) < 0) {
printf("ERROR: Cannot connect()\n");
exit(0);
}
char *org_msg = "Hello";
printf("Writing size of Hello\n");
char msg1[1];
msg1[0] = sizeof(org_msg);
write(sock, msg1, sizeof(msg1));
printf("Waiting for response from server\n");
struct sockaddr_in c_address;
socklen_t c_length = sizeof(c_address);
int new_sock = accept(sock, (struct sockaddr *) &c_address, &c_length);
printf("Reading response from server\n");
char stat[1];
read(new_sock, stat, 1);
if (atoi(stat) == 0) {
printf("Writing Hello to server\n");
write(sock, org_msg, sizeof(org_msg));
}
close(sock);
close(new_sock);
}
SERVER
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
int main(int argc, char *argv[])
{
int sock = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in s_address;
s_address.sin_family = AF_INET;
s_address.sin_port = htons(51717);
s_address.sin_addr.s_addr = INADDR_ANY;
if (bind(sock, (struct sockaddr *) &s_address, sizeof(s_address)) < 0) {
printf("ERROR: Cannot bind()\n");
exit(0);
}
listen(sock, 3);
printf("Waiting for client message\n");
struct sockaddr_in c_address;
socklen_t c_length = sizeof(c_address);
int new_sock = accept(sock, (struct sockaddr *) &c_address, &c_length);
printf("Reading client message\n");
char msg[1];
read(new_sock, msg, 1);
printf("Writing response to client\n");
char stat[1];
stat[0] = '0';
write(new_sock, stat, sizeof(stat));
printf("Waiting for client message\n");
int new_sock2 = accept(sock, (struct sockaddr *) &c_address, &c_length);
printf("Reading client message\n");
char msg2[atoi(msg)];
read(new_sock2, msg2, sizeof(msg2));
printf("MESSAGE: %s\n", msg2);
close(sock);
close(new_sock);
close(new_sock2);
}
答案 0 :(得分:3)
您不应该在已连接的套接字上调用accept()
。一旦在服务器中有一个连接的套接字(accept()
返回的套接字),你就应该继续读取和写入该套接字,直到连接关闭为止。服务器的步骤应类似于:
listen_socket = socket(...);
listen(listen_socket, ...);
connected_socket = accept(listen_socket, ...);
read(connected_socket, ...)
write(connected_socket, ...)
read(connected_socket, ...)
write(connected_socket, ...)
...
类似地,客户端应该在成功连接后继续读取和写入套接字 - 客户端的步骤应该是:
connected_socket = socket(...);
connect(connected_socket, ...);
write(connected_socket, ...);
read(connected_socket, ...);
write(connected_socket, ...);
read(connected_socket, ...);
...
答案 1 :(得分:1)
INADDR_ANY
在服务器中运行,但您的客户端需要指定它连接的主机。
如果两者都在同一台机器上,只需使用127.0.0.1或localhost(您必须进行转换以使其格式正确)
更多信息here,但简短的回答是
#define INADDR_LOOPBACK 0x7f000001
然后s_address.sin_addr.s_addr = htonl (INADDR_LOOPBACK)
答案 2 :(得分:1)
在客户端上,您尝试接受与先前连接到服务器的套接字的新连接,该套接字将绑定到系统选择的端口号。服务器永远不会尝试连接到客户端,因此客户端上的accept
调用永远不会返回(实际上它可能会返回但有错误,因为您永远不会在该套接字上调用listen
。
为什么不使用前面步骤中使用的相同套接字执行第3步?如果由于某种原因你需要一个新的套接字,你应该在客户端创建一个新的套接字,而不是重用前一个套接字(或者在前一个套接字上调用close
,然后再次调用它上面的connect
)
顺便说一句,如果您只需要IPC,那么套接字是一种非常糟糕的方式。我建议像Java RMI这样的东西。