问题描述
我希望服务器将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,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,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,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,0);
// send server the otp recieved
send(data_exchange_socket,strlen(otp),0);
// recieve server message
char* server_verdict;
recv(data_exchange_socket,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,0);
printf("Server Message: %s\n",server_message);
}
close(data_exchange_socket);
return 0;
}
我认为是因为也许我们只能用一个data_exchange_socket接收一次。但是后来我发现客户端代码不正确。
请告诉我以上内容是否正确。我不明白为什么它不起作用。
解决方法
您没有正确处理字符串传输。您不是通过发送字符串长度或使用空终止符来构造字符串,以便接收方知道何时停止读取每个字符串。而且,您没有为recv()
分配任何要读取的内存。或者考虑到TCP是流的事实,因此send()
和recv()
之间没有1:1的关系,因此可以进行部分发送/读取。
尝试更多类似方法:
常用:
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 == '\0') ? (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 != '\0');
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,size_t size)
{
char *pdata = data;
int numRecv;
while (size > 0)
{
numRecv = recv(sock,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,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] = '\0';
*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,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;
}