I am building a basic client and server in TCP. it’s working except when the key gets kinda large. It just sends back and forth keys until the end of time. When it gets bigger (aka 4096) the read() statement will randomly get a null and then break the key into two msgs which then breaks the cycle.
I’m really not sure why it’s doing this, the server code is working as it has been tested with other clients, so something is wrong with my client. Any ideas (it’s pretty short):
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define BUFFER_LENGTH 5120
// Error message taken from reference
void error(const char *msg)
{
printf("%s\n", msg);
exit(0);
}
int main(int argc, char *argv[])
{
int sockfd, portNumber, n;
struct sockaddr_in serv_addr;
struct hostent *server;
// Invalid arguments
if (argc < 4)
exit(0);
else if (atoi(argv[3]) < 1 || atoi(argv[3]) > 4096)
exit(0);
char buffer[BUFFER_LENGTH];
bzero(buffer, BUFFER_LENGTH);
char buffer2[BUFFER_LENGTH];
bzero(buffer2, BUFFER_LENGTH);
strcpy(buffer2, "Connect. Key length: ");
strcpy(buffer, strcat(buffer2, argv[3]));
portNumber = atoi(argv[2]); // Get port number in int format
sockfd = socket(AF_INET, SOCK_STREAM, 0); // Create socket connection to server using internet constants
// Did we open the socket succesfully?
if (sockfd < 0)
error("Error opening socket.");
// Is the IP Address valid?
server = gethostbyname(argv[1]);
if (server == NULL)
error("Could not connect to server. Terminating.");
// Initialize to zero and then set
// Taken from reference
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr, server->h_length);
serv_addr.sin_port = htons(portNumber);
if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
error("Could not connect to server. Terminating.");
short connected = 1;
do
{
// Send initial request on first pass
// Afterwards send the resposne we were given
printf("Sending: %s\n", buffer);
printf("Length of msg: %d\n", (strlen(buffer) + 1));
n = write(sockfd, buffer, strlen(buffer) + 1);
if (n < 1)
error("Failed to send Message. Terminating.");
// Get session key response
bzero(buffer, BUFFER_LENGTH);
n = read(sockfd, buffer, BUFFER_LENGTH);
if (n < 1)
error("Could not fetch result. Terminating.");
// Stop
if (strcmp(buffer, "Invalid session key. Terminating.") == 0)
break;
printf("%s\n", buffer);
sleep(1);
} while (connected == 1);
// Done (this should never be reached in this client)
error("Could not fetch result. Terminating.");
close(sockfd);
return 0;
}
Don’t use
strcpy(), or anystr*()function, on binary data. You’re not dealing with strings. Usememcpy()and specify the number of bytes you want to copy.The
str*()functions operate on strings; a string is defined by the C standard as “a contiguous sequence of characters terminated by and including the first null character”. But in binary data, a null character (zero byte) is just another chunk of data that doesn’t necessarily have any significance.If your binary data looks like this (in hex):
then
strcpy()will ignore everything after the00byte. Worse, if your binary data looks like:with no null bytes, then
strcpy(), orstrlen(), or any string function will continue past the end of your buffer, with unpredictable results.