I've created a TCP Server/Client in C++. The client takes an input char array from stdin. The client then sends it to the server. The server's job is to respond with a modified form of the message from the client. The server's modification: replace the first char of the input message with 'X'
It works as expected on the first input message, but the client receives malformed data starting with the second message.
./client.bin output:
helloworld <-----stdin
TX: helloworld
RX: Xelloworld
test <-----stdin
TX: test
RX: 0est
somethingelse <-----stdin
TX: somethingelse
RX: Xest
./echoserver.bin output:
RX: helloworld
TX: Xelloworld
RX: test
TX: Xest
RX: somethingelse
TX: Xomethingelse
echoserver.cc:
#include <iostream>
#include <string>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#define PORT 8080
#define BUF_SIZE 1024
void error_exit(std::string text)
{
std::cerr << text << std::endl;
exit(1);
}
int main()
{
int sd;
int connection;
int valread;
int opt = 1;
char buffer[BUF_SIZE] = {0};
if ((sd = socket(AF_INET,SOCK_STREAM,0)) == 0)
error_exit("socket failure");
if (setsockopt(sd, SOL_SOCKET,SO_REUSEADDR,
&opt, sizeof(opt)))
error_exit("failed to set socket opts");
sockaddr_in address;
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(PORT);
if (bind(sd, (struct sockaddr *)&address, sizeof(address)) != 0)
error_exit("failed to bind socket");
if (listen(sd,3) < 0)
error_exit("failed to listen");
int addrlen = sizeof(address);
if ((connection = accept(sd, (struct sockaddr*)&address,
(socklen_t*)&addrlen)) < 0)
error_exit("failed to accept socket link");
while (1)
{
memset(&buffer[0],'0', sizeof(buffer));
if (recv(connection,buffer,BUF_SIZE-1,0) <= 0)
break;
std::cout << "RX: " << buffer << std::endl;
buffer[0] = 'X';
std::cout << "TX: " << buffer << std::endl;
send(connection,buffer,BUF_SIZE,0);
}
return 0;
}
client.cc
#include <iostream>
#include <string>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <arpa/inet.h>
#define PORT 8080
#define BUF_SIZE 1024
void error_exit(std::string text)
{
std::cerr << text << std::endl;
exit(1);
}
int main()
{
int sd;
int valread;
struct sockaddr_in address;
struct sockaddr_in server_addr;
char buffer[BUF_SIZE] = {0};
if ((sd = socket(AF_INET,SOCK_STREAM,0)) < 0)
error_exit("failed to create socket");
memset(&server_addr, '0', sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT);
if (inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr) <= 0)
error_exit("Invalid Address");
if (connect(sd,(struct sockaddr*)&server_addr,sizeof(server_addr)) < 0)
error_exit("Connection Failure");
std::cin >> buffer;
while (buffer[0] != 'q')
{
std::cout << "TX: " << buffer << std::endl;
send(sd,buffer,BUF_SIZE-1,0);
if ( recv(sd,buffer,BUF_SIZE-1,0) <= 0)
error_exit("Failed to receive");
std::cout << "RX: " << buffer << std::endl;
memset(&buffer[0],'0', sizeof(buffer));
std::cin >> buffer;
}
return 0;
}
your send calls are always sending 1023 bytes but your recv calls don't necessarily download all of that data, you either need to call recv in a loop until you have all the sent data or pass the MSG_WAITALL flag.