[英]BSD socket not working
UPDATE: src updated based on suggestions. 更新:src根据建议进行了更新。 strcat a \\n\\0 onto command and changing sizeof.
在命令上加上\\ n \\ 0并更改sizeof。 Client has a "Succeed" on sending, but server never "succeeds" on receiving.
客户端在发送时具有“成功”,但是服务器在接收时从未“成功”。
I have put a lot of working into trying to get a regular old TCP socket working. 我做了很多工作,试图使常规的旧TCP套接字正常工作。 I basically have a simple client and a server setup.
我基本上有一个简单的客户端和服务器设置。 Currently I don't receive anything at all on my server, and I only get 4 bytes on my client ("GOTY" in this example).
目前,我的服务器上什么也没有收到,我的客户端上仅得到4个字节(在此示例中为“ GOTY”)。
Server output outputs this and moves on: 服务器输出输出并继续:
RECEIVED (null)
Client output just blocks and never stops. 客户端输出只是阻塞而不会停止。 If I kill the server I get this output
如果我杀死服务器,则会得到此输出
Connect success
Received Response:
SERVER 服务器
int Server::update(char *getbuf)
{
int ready = poll(pollfds, 1, 100);
if (ready == -1)
{
logger.info("Poll failed");
return FALSE;
}
if (pollfds[0].revents & POLLIN)
{
ssize_t z;
logger.info("Connection available");
struct sockaddr_in client_address;
memset(&client_address, 0, sizeof client_address);
socklen_t alen = sizeof(client_address);
// ACCEPT
clientsocket = accept(serversocket, (struct sockaddr *)&client_address, &alen);
if(!clientsocket)
logger.fail("Accept Fail");
// READ
z = recv(clientsocket, getbuf, 512, MSG_WAITALL);
if (z < 0)
fprintf(stderr,"receive failure\n");
else
fprintf(stderr,"receive succeed\n");
getbuf[z] = 0;
respond(getbuf);
//closeConnection();
logger.data("RECEIVED %s", getbuf);
getbuf[z] = 0;
return TRUE;
}
return FALSE;
}
void Server::respond(char *response)
{
// SEND
ssize_t z;
z = send(clientsocket, response, strlen(response), 0);
if (z < 0)
fprintf(stderr,"send failure\n");
else
fprintf(stderr,"send succeed\n");
}
CLIENT 客户
I added the client code. 我添加了客户端代码。 I now use strlen but it doesn't seem to help things.
我现在使用strlen,但似乎无济于事。
int main(int argc, char **argv)
{
int abort = 0;
int port;
in_addr_t address;
char *command;
ssize_t z;
int com_socket;
struct sockaddr_in server_address;
struct timeval timeout;
int opt;
int val = 0;
char getbuf[512];
//Defaults
address = inet_addr("127.0.0.1");
port = 4949;
//INCLUDED ARGUMENTS FROM CLI
while((opt = getopt(argc, argv, "a:p:c:")) > 0)
{
switch(opt)
{
case 'a':
address = inet_addr(optarg);
break;
case 'p':
port = atoi(optarg);
break;
case 'c':
abort = 1;
command = (char *)optarg;
break;
default:
fprintf(stderr, "-a IPADDRESS -p PORT -c COMMAND\n",argv[0]);
}
}
// Server
memset(&server_address, 0, sizeof(server_address));
server_address.sin_family = AF_INET;
server_address.sin_port = htons(port);
server_address.sin_addr.s_addr = address;
if (server_address.sin_addr.s_addr == INADDR_NONE)
fprintf(stderr, "Server address failed\n");
if(!abort)
{
fprintf(stderr, "No Command given\n");
fprintf(stderr, "-a IPADDRESS -p PORT -C COMMAND\n");
exit(0);
}
else
{
fprintf(stderr, "Address %s Port %d Command %s\n", inet_ntoa(server_address.sin_addr), port, command);
}
// Create com_socket
com_socket = socket(PF_INET, SOCK_STREAM, 0);
if (com_socket == -1)
fprintf(stderr, "Socket failed\n");
/*
// Client
struct sockaddr_in client_address;
memset(&client_address,0,sizeof client_address);
client_address.sin_family = AF_INET;
client_address.sin_port = 0;
client_address.sin_addr.s_addr = ntohl(INADDR_ANY);
if (client_address.sin_addr.s_addr == INADDR_NONE)
fprintf(stderr, "Client address failed\n");
// Bind
z= bind(com_socket, (struct sockaddr *)&client_address, sizeof (client_address));
if ( z == -1 )
fprintf(stderr,"Binding port\n");
*/
timeout.tv_sec = 2; /* 2 seconds */
timeout.tv_usec = 0; /* + 0 usec */
socklen_t addrlen = sizeof(struct sockaddr_in);
// Connect
//z = connectWithTimeout(com_socket, (struct sockaddr *) &server_address, len_inet, &timeout);
z = connect(com_socket, (struct sockaddr *) &server_address, sizeof(server_address));
if(z == -1)
{
if(errno == EINPROGRESS)
{
fprintf(stderr, "EINPROGRESS non block start\n");
}
if(errno == EALREADY)
{
fprintf(stderr, "EALREADY non block subsequent request\n");
}
fprintf(stderr, "Connect failed\n");
}
else
fprintf(stderr, "Connect success\n");
strcat(command, "\n\0");
// SEND
z = send(com_socket, command, strlen(command)+2, 0);
if (z < 0)
fprintf(stderr,"send failure\n");
else
fprintf(stderr,"send succeed\n");
// READ
z = recv(com_socket, getbuf, 512, MSG_WAITALL);
if (z < 0)
fprintf(stderr,"receive failure\n");
else
fprintf(stderr,"receive succeed\n");
// Output
fprintf(stderr, "Received Response: %s\n", getbuf);
close(com_socket);
exit(1);
}
I just have no idea why this is not working. 我只是不知道为什么这不起作用。 I've been over it again and again.
我一次又一次地经历过。
It's a embedded Linux system. 这是一个嵌入式Linux系统。
In the server: this is just plain wrong. 在服务器中:这是完全错误的。 strlen() returns the length of the string that was in the buffer before the read() /recv().
strlen()返回read()/ recv() 之前缓冲区中字符串的长度。
// READ
z = recv(clientsocket, getbuf, strlen(getbuf), MSG_WAITALL);
if (z < 0)
fprintf(stderr,"receive failure\n");
Also: in respond(), strlen() assumes that the response "string" is null-termated. 另外:在response()中,strlen()假定响应“字符串”为空值。 It is not.
它不是。
z = send(clientsocket, response, strlen(response), 0);
And the same type of error appears to be present in the client code. 并且客户端代码中似乎存在相同类型的错误。
UPDATE: since the OP does not know how to live without string functions, I'll illustrate how this could be done. 更新:由于OP不知道如何不使用字符串函数,因此我将说明如何实现。
... snipped ...
// READ
z = recv(clientsocket, getbuf, 512, MSG_WAITALL);
if (z < 0) {
// .... if (errno == EAGAIN) continue;
fprintf(stderr,"receive failure %d(%s) \n"
, errno, strerror(errno) );
break; }
fprintf(stderr,"receive succeed\n");
respond(getbuf, z);
return TRUE;
}
return FALSE;
}
void respond(char *response, size_t siz)
{
// SEND
size_t done;
ssize_t z;
for (done = 0; done < siz; done += z) {
z = send(clientsocket, response+done, siz-done, 0);
if (z < 0) {
if (errno == EAGAIN) continue;
fprintf(stderr,"send failure %d(%s)\n"
, errno, strerror(errno) );
break; }
fprintf(stderr,"send succeed\n");
}
}
Since you have not actually shared the source of your "respond" function, my psychic powers tell me it looks something like this: 由于您实际上尚未共享“响应”功能的来源,因此我的心灵力量告诉我它看起来像这样:
void Server::respond(char* str)
{
send(clientsock, str, sizeof(str), 0);
}
As such, "sizeof(str)" is evaluating to 4 because that's the size of a pointer on your machine. 因此,“ sizeof(str)”的计算结果为4,因为这是您计算机上指针的大小。 That is consistent with the client receiving "GOTY" (the first 4 bytes of the message you intended to send).
这与客户端收到“ GOTY”(您要发送的消息的前4个字节)一致。
Change it to the following: 将其更改为以下内容:
void Server::respond(char* str)
{
send(clientsock, str, strlen(str), 0);
}
Also, you should never assume that that send and recv will return a value equal to the amount of data you expected to send or receive. 另外,您永远不要假定send和recv将返回等于您希望发送或接收的数据量的值。 Hence, you should loop on non-blocking calls to send/recv until the entire message has been sent or consumed.
因此,您应该循环发送/接收非阻塞调用,直到发送或使用了整个消息为止。
Send operations on sockets are often buffered so it's possible your respond function is not flushing all that data. 套接字上的发送操作通常被缓冲,因此您的响应功能可能没有刷新所有数据。 Try a flush operation at the end of
respond()
to get the extra data. 在
respond()
的末尾尝试刷新操作以获取额外的数据。
It's looks to me like you're seeing blocking behaviour you might want to look into how blocking/non-blocking affects sockets. 在我看来,您似乎正在查看阻塞行为,因此您可能希望了解阻塞/非阻塞如何影响套接字。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.