从单个客户端接收多次。我只能从客户端接收一次,然后每个响应都是 NULL
Receiving multiple times from a single client. I can only recieve from the client once and then every response is NULL
我希望服务器向客户端发送一个 OTP(一次性密码)。然后客户端将密码发送回服务器,如果它们匹配则进行进一步的对话。
此代码用于服务器端:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <errno.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char* argv[])
{
// Create a listen socket
int listen_socket = socket(PF_INET, SOCK_STREAM, 0);
// Create Local Server address and initialise family, port number, IP address
struct sockaddr_in server_address;
server_address.sin_family = AF_INET;
server_address.sin_port = htons(10000);
server_address.sin_addr.s_addr = INADDR_ANY;
// bind listen socket with local server address
bind(listen_socket, (struct sockaddr*)&server_address, sizeof(struct sockaddr_in));
// listen for a connection
listen(listen_socket, 10);
// accept a connection to create socket for data exchange
int data_exchange_socket = accept(listen_socket, NULL, NULL);
//--------------------------------- LOGIC ----------------------------------------
//OTP for authentication
char* server_password = "vikas@hplap";
// send OTP to client
send(data_exchange_socket, server_password, strlen(server_password), 0);
// recieve OTP
char* client_password;
recv(data_exchange_socket, client_password, 50, 0);
// authenticate
if(strcmp(server_password, client_password) == 0)
{
// Correct OTP sent by client
char* server_verdict = "Correct";
send(data_exchange_socket, server_verdict, strlen(server_verdict), 0);
// get client message
char* client_message;
recv(data_exchange_socket, client_message, 50, 0);
printf("Client Message: %s\n", client_message);
//server respond with hello
char* server_response = "Hello, Press any key to exit...";
send(data_exchange_socket, server_response, strlen(server_response), 0);
printf("Data sent\n"); // This doesn't execute
}
else
{
// handle wrong OTP by client
char* server_response = "Incorrect OTP entered!";
send(data_exchange_socket, server_response, strlen(server_response), 0);
}
// shut down server
printf("Server Closed :)\n"); // This is also not executed
close(listen_socket);
return 0;
}
这是客户端的代码:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <errno.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char* argv[])
{
// create socket for data exchange
int data_exchange_socket = socket(PF_INET, SOCK_STREAM, 0);
// create remote server address
struct sockaddr_in server_address;
server_address.sin_family = AF_INET;
server_address.sin_port = htons(10000);
server_address.sin_addr.s_addr = INADDR_ANY;
// try to connect with server
int status=connect(data_exchange_socket, (struct sockaddr *)&server_address, sizeof(struct sockaddr_in));
if(status==-1)
{
printf("\n connection error.....");
}
// recieve OTP from server
char* otp;
recv(data_exchange_socket, otp, 50, 0);
// send server the otp recieved
send(data_exchange_socket, otp, strlen(otp), 0);
// recieve server message
char* server_verdict;
recv(data_exchange_socket, server_verdict, 50, 0);
if(strcmp(server_verdict, "Correct") == 0)
{
// Send "Hi" to server
char* client_response = "Hi";
send(data_exchange_socket, client_response, strlen(client_response), 0);
// recieve server message
char* server_message;
recv(data_exchange_socket, server_message, 50, 0);
printf("Server Message: %s\n", server_message);
}
close(data_exchange_socket);
return 0;
}
我想是因为一个data_exchange_socket可能我们只能收到一次。但是后来我发现客户端代码不是这样。
请告诉我以上是否属实。我不明白为什么它不起作用。
您没有正确处理您的字符串传输。您不是通过发送字符串长度或空终止符以这种方式构建字符串,以便接收方可以知道何时停止读取每个字符串。而且您没有为 recv()
分配任何内存来读取。或者考虑到 TCP 是一个流,所以 send()
和 recv()
之间没有 1:1 关系,部分 sends/reads 是可能的。
尝试更像这样的东西:
常见:
int sendString(int sock, const char *str)
{
size_t len = strlen(str) + 1;
int numSent;
while (len > 0)
{
numSent = send(sock, str, len, 0);
if (numSent < 0)
return -1;
str += numSent;
len -= numSent;
}
return 0;
}
int recvString(int sock, char **msg)
{
size_t len = 0, cap = 0, size;
char ch, *newmsg;
int numRecv;
*msg = NULL;
do
{
numRecv = recv(sock, &ch, 1, 0);
if (numRecv <= 0)
{
free(*msg);
*msg = NULL;
return numRecv;
}
if (len == cap)
{
size = (ch == '[=10=]') ? (len + 1) : (len + 50);
newmsg = realloc(*msg, size);
if (newmsg == NULL)
{
free(*msg);
*msg = NULL;
return -1;
}
memcpy(newmsg, *msg, len);
*msg = newmsg;
cap = size;
}
(*msg)[len] = ch;
++len;
}
while (ch != '[=10=]');
return 1;
}
或者:
int sendRaw(int sock, void *data, size_t size)
{
char *pdata = data;
int numSent;
while (size > 0)
{
numSent = send(sock, pdata, size, 0);
if (numSent < 0)
return -1;
pdata += numSent;
size -= numSent;
}
return 0;
}
int recvRaw(int sock, void *data, size_t size)
{
char *pdata = data;
int numRecv;
while (size > 0)
{
numRecv = recv(sock, pdata, size, 0);
if (numRecv <= 0)
return numRecv;
pdata += numRecv;
size -= numRecv;
}
return 1;
}
int sendUInt32(int sock, uint32_t val)
{
val = htonl(val);
return sendRaw(sock, &val, sizeof(val));
}
int recvUInt32(int sock, uint32_t *val)
{
int res = recvRaw(sock, val, sizeof(*val));
if (res <= 0) return res;
*val = ntohl(*val);
return 1;
}
int sendString(int sock, const char *str)
{
size_t len = strlen(str);
if (sendUInt32(sock, len) < 0) return -1;
return sendRaw(sock, str, len);
}
int recvString(int sock, char **msg)
{
*msg = NULL;
uint32_t len;
int res = recvUInt32(sock, &len);
if (res <= 0)
return res;
char *newmsg = malloc(len + 1);
if (newmsg == NULL)
return -1;
res = recvRaw(sock, newmsg, len);
if (res <= 0)
{
free(newmsg);
return res;
}
newmsg[len] = '[=11=]';
*msg = newmsg;
return 1;
}
那么你可以这样做:
服务器:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <errno.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
#include "Common.h"
int main(int argc, char* argv[])
{
// Create a listen socket
int listen_socket = socket(PF_INET, SOCK_STREAM, 0);
if (listen_socket < 0)
{
perror("Error creating listening socket");
return -1;
}
// Create Local Server address and initialize family, port number, IP address
struct sockaddr_in server_address;
server_address.sin_family = AF_INET;
server_address.sin_port = htons(10000);
server_address.sin_addr.s_addr = INADDR_ANY;
// bind listen socket with local server address
if (bind(listen_socket, (struct sockaddr*)&server_address, sizeof(struct sockaddr_in)) < 0)
{
perror("Error binding listening socket");
close(listen_socket);
return -1;
}
// listen for a connection
if (listen(listen_socket, 10) < 0)
{
perror("Error opening listening socket");
close(listen_socket);
return -1;
}
// accept a connection to create socket for data exchange
int data_exchange_socket = accept(listen_socket, NULL, NULL);
if (data_exchange_socket < 0)
{
perror("Error accepting a client");
close(listen_socket);
return -1;
}
//--------------------------------- LOGIC ----------------------------------------
//OTP for authentication
// send OTP to client
if (sendString(data_exchange_socket, "vikas@hplap") < 0)
{
perror("Error sending password to client");
close(data_exchange_socket);
close(listen_socket);
return 0;
}
// receive OTP
char* client_password;
int res = recvString(data_exchange_socket, &client_password);
if (res <= 0)
{
if (res < 0)
perror("Error receiving password from client");
else
printf("Disconnected while receiving password from client\n");
close(data_exchange_socket);
close(listen_socket);
return 0;
}
// authenticate
int res = strcmp(server_password, client_password);
free(client_password);
if (res == 0)
{
// Correct OTP sent by client
if (sendString(data_exchange_socket, "Correct") < 0)
{
perror("Error sending verdict to client");
close(data_exchange_socket);
close(listen_socket);
return 0;
}
// get client message
char* client_message;
res = recvString(data_exchange_socket, &client_message);
if (res <= 0)
{
if (res < 0)
perror("Error receiving message from client");
else
printf("Disconnected while receiving message from client\n");
close(data_exchange_socket);
close(listen_socket);
return 0;
}
printf("Client Message: %s\n", client_message);
free(client_message);
//server respond with hello
if (sendString(data_exchange_socket, "Hello, Press any key to exit...") < 0)
{
perror("Error sending message to client");
close(data_exchange_socket);
close(listen_socket);
return 0;
}
printf("Data sent\n"); // This doesn't execute
}
else
{
// handle wrong OTP by client
if (sendString(data_exchange_socket, "Incorrect OTP entered!") < 0)
{
perror("Error sending verdict to client");
close(data_exchange_socket);
close(listen_socket);
return 0;
}
}
// shut down server
printf("Server Closed :)\n"); // This is also not executed
close(data_exchange_socket);
close(listen_socket);
return 0;
}
客户:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <errno.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
#include "Common.h"
int main(int argc, char* argv[])
{
// create socket for data exchange
int data_exchange_socket = socket(PF_INET, SOCK_STREAM, 0);
if (data_exchange_socket < 0)
{
perror("Error creating socket");
return -1;
}
// create remote server address
struct sockaddr_in server_address;
server_address.sin_family = AF_INET;
server_address.sin_port = htons(10000);
server_address.sin_addr.s_addr = inet_addr("127.0.0.1");
// try to connect with server
if (connect(data_exchange_socket, (struct sockaddr *)&server_address, sizeof(struct sockaddr_in)) < 0)
{
perror("Error connecting to server");
close(data_exchange_socket);
return -1;
}
// recieve OTP from server
char* otp;
int res = recvString(data_exchange_socket, &otp);
if (res <= 0)
{
if (res < 0)
perror("Error receiving password from server");
else
printf("Disconnected while receiving password from server\n");
close(data_exchange_socket);
return -1;
}
// send server the otp received
if (sendString(data_exchange_socket, otp) < 0)
{
perror("Error sending password to server");
free(otp);
close(data_exchange_socket);
return -1;
}
free(otp);
// receive server message
char* server_verdict;
res = recvString(data_exchange_socket, &server_verdict);
if (res <= 0)
{
if (res < 0)
perror("Error receiving verdict from server");
else
printf("Disconnected while receiving verdict from server\n");
close(data_exchange_socket);
return -1;
}
res = strcmp(server_verdict, "Correct");
free(server_verdict);
if (res == 0)
{
// Send "Hi" to server
if (sendString(data_exchange_socket, "Hi") < 0)
{
perror("Error sending message to server");
close(data_exchange_socket);
return -1;
}
// recieve server message
char* server_message;
res = recvString(data_exchange_socket, &server_message);
if (res <= 0)
{
if (res < 0)
perror("Error receiving message from server");
else
printf("Disconnected while receiving message from server\n");
close(data_exchange_socket);
return -1;
}
printf("Server Message: %s\n", server_message);
free(server_message);
}
close(data_exchange_socket);
return 0;
}
我希望服务器向客户端发送一个 OTP(一次性密码)。然后客户端将密码发送回服务器,如果它们匹配则进行进一步的对话。
此代码用于服务器端:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <errno.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char* argv[])
{
// Create a listen socket
int listen_socket = socket(PF_INET, SOCK_STREAM, 0);
// Create Local Server address and initialise family, port number, IP address
struct sockaddr_in server_address;
server_address.sin_family = AF_INET;
server_address.sin_port = htons(10000);
server_address.sin_addr.s_addr = INADDR_ANY;
// bind listen socket with local server address
bind(listen_socket, (struct sockaddr*)&server_address, sizeof(struct sockaddr_in));
// listen for a connection
listen(listen_socket, 10);
// accept a connection to create socket for data exchange
int data_exchange_socket = accept(listen_socket, NULL, NULL);
//--------------------------------- LOGIC ----------------------------------------
//OTP for authentication
char* server_password = "vikas@hplap";
// send OTP to client
send(data_exchange_socket, server_password, strlen(server_password), 0);
// recieve OTP
char* client_password;
recv(data_exchange_socket, client_password, 50, 0);
// authenticate
if(strcmp(server_password, client_password) == 0)
{
// Correct OTP sent by client
char* server_verdict = "Correct";
send(data_exchange_socket, server_verdict, strlen(server_verdict), 0);
// get client message
char* client_message;
recv(data_exchange_socket, client_message, 50, 0);
printf("Client Message: %s\n", client_message);
//server respond with hello
char* server_response = "Hello, Press any key to exit...";
send(data_exchange_socket, server_response, strlen(server_response), 0);
printf("Data sent\n"); // This doesn't execute
}
else
{
// handle wrong OTP by client
char* server_response = "Incorrect OTP entered!";
send(data_exchange_socket, server_response, strlen(server_response), 0);
}
// shut down server
printf("Server Closed :)\n"); // This is also not executed
close(listen_socket);
return 0;
}
这是客户端的代码:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <errno.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char* argv[])
{
// create socket for data exchange
int data_exchange_socket = socket(PF_INET, SOCK_STREAM, 0);
// create remote server address
struct sockaddr_in server_address;
server_address.sin_family = AF_INET;
server_address.sin_port = htons(10000);
server_address.sin_addr.s_addr = INADDR_ANY;
// try to connect with server
int status=connect(data_exchange_socket, (struct sockaddr *)&server_address, sizeof(struct sockaddr_in));
if(status==-1)
{
printf("\n connection error.....");
}
// recieve OTP from server
char* otp;
recv(data_exchange_socket, otp, 50, 0);
// send server the otp recieved
send(data_exchange_socket, otp, strlen(otp), 0);
// recieve server message
char* server_verdict;
recv(data_exchange_socket, server_verdict, 50, 0);
if(strcmp(server_verdict, "Correct") == 0)
{
// Send "Hi" to server
char* client_response = "Hi";
send(data_exchange_socket, client_response, strlen(client_response), 0);
// recieve server message
char* server_message;
recv(data_exchange_socket, server_message, 50, 0);
printf("Server Message: %s\n", server_message);
}
close(data_exchange_socket);
return 0;
}
我想是因为一个data_exchange_socket可能我们只能收到一次。但是后来我发现客户端代码不是这样。
请告诉我以上是否属实。我不明白为什么它不起作用。
您没有正确处理您的字符串传输。您不是通过发送字符串长度或空终止符以这种方式构建字符串,以便接收方可以知道何时停止读取每个字符串。而且您没有为 recv()
分配任何内存来读取。或者考虑到 TCP 是一个流,所以 send()
和 recv()
之间没有 1:1 关系,部分 sends/reads 是可能的。
尝试更像这样的东西:
常见:
int sendString(int sock, const char *str)
{
size_t len = strlen(str) + 1;
int numSent;
while (len > 0)
{
numSent = send(sock, str, len, 0);
if (numSent < 0)
return -1;
str += numSent;
len -= numSent;
}
return 0;
}
int recvString(int sock, char **msg)
{
size_t len = 0, cap = 0, size;
char ch, *newmsg;
int numRecv;
*msg = NULL;
do
{
numRecv = recv(sock, &ch, 1, 0);
if (numRecv <= 0)
{
free(*msg);
*msg = NULL;
return numRecv;
}
if (len == cap)
{
size = (ch == '[=10=]') ? (len + 1) : (len + 50);
newmsg = realloc(*msg, size);
if (newmsg == NULL)
{
free(*msg);
*msg = NULL;
return -1;
}
memcpy(newmsg, *msg, len);
*msg = newmsg;
cap = size;
}
(*msg)[len] = ch;
++len;
}
while (ch != '[=10=]');
return 1;
}
或者:
int sendRaw(int sock, void *data, size_t size)
{
char *pdata = data;
int numSent;
while (size > 0)
{
numSent = send(sock, pdata, size, 0);
if (numSent < 0)
return -1;
pdata += numSent;
size -= numSent;
}
return 0;
}
int recvRaw(int sock, void *data, size_t size)
{
char *pdata = data;
int numRecv;
while (size > 0)
{
numRecv = recv(sock, pdata, size, 0);
if (numRecv <= 0)
return numRecv;
pdata += numRecv;
size -= numRecv;
}
return 1;
}
int sendUInt32(int sock, uint32_t val)
{
val = htonl(val);
return sendRaw(sock, &val, sizeof(val));
}
int recvUInt32(int sock, uint32_t *val)
{
int res = recvRaw(sock, val, sizeof(*val));
if (res <= 0) return res;
*val = ntohl(*val);
return 1;
}
int sendString(int sock, const char *str)
{
size_t len = strlen(str);
if (sendUInt32(sock, len) < 0) return -1;
return sendRaw(sock, str, len);
}
int recvString(int sock, char **msg)
{
*msg = NULL;
uint32_t len;
int res = recvUInt32(sock, &len);
if (res <= 0)
return res;
char *newmsg = malloc(len + 1);
if (newmsg == NULL)
return -1;
res = recvRaw(sock, newmsg, len);
if (res <= 0)
{
free(newmsg);
return res;
}
newmsg[len] = '[=11=]';
*msg = newmsg;
return 1;
}
那么你可以这样做:
服务器:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <errno.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
#include "Common.h"
int main(int argc, char* argv[])
{
// Create a listen socket
int listen_socket = socket(PF_INET, SOCK_STREAM, 0);
if (listen_socket < 0)
{
perror("Error creating listening socket");
return -1;
}
// Create Local Server address and initialize family, port number, IP address
struct sockaddr_in server_address;
server_address.sin_family = AF_INET;
server_address.sin_port = htons(10000);
server_address.sin_addr.s_addr = INADDR_ANY;
// bind listen socket with local server address
if (bind(listen_socket, (struct sockaddr*)&server_address, sizeof(struct sockaddr_in)) < 0)
{
perror("Error binding listening socket");
close(listen_socket);
return -1;
}
// listen for a connection
if (listen(listen_socket, 10) < 0)
{
perror("Error opening listening socket");
close(listen_socket);
return -1;
}
// accept a connection to create socket for data exchange
int data_exchange_socket = accept(listen_socket, NULL, NULL);
if (data_exchange_socket < 0)
{
perror("Error accepting a client");
close(listen_socket);
return -1;
}
//--------------------------------- LOGIC ----------------------------------------
//OTP for authentication
// send OTP to client
if (sendString(data_exchange_socket, "vikas@hplap") < 0)
{
perror("Error sending password to client");
close(data_exchange_socket);
close(listen_socket);
return 0;
}
// receive OTP
char* client_password;
int res = recvString(data_exchange_socket, &client_password);
if (res <= 0)
{
if (res < 0)
perror("Error receiving password from client");
else
printf("Disconnected while receiving password from client\n");
close(data_exchange_socket);
close(listen_socket);
return 0;
}
// authenticate
int res = strcmp(server_password, client_password);
free(client_password);
if (res == 0)
{
// Correct OTP sent by client
if (sendString(data_exchange_socket, "Correct") < 0)
{
perror("Error sending verdict to client");
close(data_exchange_socket);
close(listen_socket);
return 0;
}
// get client message
char* client_message;
res = recvString(data_exchange_socket, &client_message);
if (res <= 0)
{
if (res < 0)
perror("Error receiving message from client");
else
printf("Disconnected while receiving message from client\n");
close(data_exchange_socket);
close(listen_socket);
return 0;
}
printf("Client Message: %s\n", client_message);
free(client_message);
//server respond with hello
if (sendString(data_exchange_socket, "Hello, Press any key to exit...") < 0)
{
perror("Error sending message to client");
close(data_exchange_socket);
close(listen_socket);
return 0;
}
printf("Data sent\n"); // This doesn't execute
}
else
{
// handle wrong OTP by client
if (sendString(data_exchange_socket, "Incorrect OTP entered!") < 0)
{
perror("Error sending verdict to client");
close(data_exchange_socket);
close(listen_socket);
return 0;
}
}
// shut down server
printf("Server Closed :)\n"); // This is also not executed
close(data_exchange_socket);
close(listen_socket);
return 0;
}
客户:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <errno.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
#include "Common.h"
int main(int argc, char* argv[])
{
// create socket for data exchange
int data_exchange_socket = socket(PF_INET, SOCK_STREAM, 0);
if (data_exchange_socket < 0)
{
perror("Error creating socket");
return -1;
}
// create remote server address
struct sockaddr_in server_address;
server_address.sin_family = AF_INET;
server_address.sin_port = htons(10000);
server_address.sin_addr.s_addr = inet_addr("127.0.0.1");
// try to connect with server
if (connect(data_exchange_socket, (struct sockaddr *)&server_address, sizeof(struct sockaddr_in)) < 0)
{
perror("Error connecting to server");
close(data_exchange_socket);
return -1;
}
// recieve OTP from server
char* otp;
int res = recvString(data_exchange_socket, &otp);
if (res <= 0)
{
if (res < 0)
perror("Error receiving password from server");
else
printf("Disconnected while receiving password from server\n");
close(data_exchange_socket);
return -1;
}
// send server the otp received
if (sendString(data_exchange_socket, otp) < 0)
{
perror("Error sending password to server");
free(otp);
close(data_exchange_socket);
return -1;
}
free(otp);
// receive server message
char* server_verdict;
res = recvString(data_exchange_socket, &server_verdict);
if (res <= 0)
{
if (res < 0)
perror("Error receiving verdict from server");
else
printf("Disconnected while receiving verdict from server\n");
close(data_exchange_socket);
return -1;
}
res = strcmp(server_verdict, "Correct");
free(server_verdict);
if (res == 0)
{
// Send "Hi" to server
if (sendString(data_exchange_socket, "Hi") < 0)
{
perror("Error sending message to server");
close(data_exchange_socket);
return -1;
}
// recieve server message
char* server_message;
res = recvString(data_exchange_socket, &server_message);
if (res <= 0)
{
if (res < 0)
perror("Error receiving message from server");
else
printf("Disconnected while receiving message from server\n");
close(data_exchange_socket);
return -1;
}
printf("Server Message: %s\n", server_message);
free(server_message);
}
close(data_exchange_socket);
return 0;
}