Receiving Only Necessary Data with C++ Socket

Receiving all data sent with C sockets

If you really have no protocol defined, then all you can do is accept groups of bytes from the client as they arrive. Without a defined protocol, there is no way to know that you have received "all the bytes" that the client sent, since there is always the possibility that a network failure occurred somewhere between the client and your server during transmission, causing the last part of the stream not to arrive at the server. In that case, you would get the usual end-of-stream indication from the TCP socket (e.g. recv() returning 0, or EWOULDBLOCK if you are using non-blocking sockets), so you would know that you aren't going to receive any more data from the client (because the TCP connection is now disconnected)... but that isn't quite the same thing as knowing you have received all of the data the client meant for you receive.

Depending on your application, that might be good enough. If not, then you'll have to work out a protocol, and trust that your clients will abide by the rules of that protocol. Having the client send a header first saying how many bytes it plans to send is a good approach; or having it send some special "Okay, that's all I meant to send" indicator is also possible (although if you do it that way, you have to watch out for false positives if the special indicator could appear by chance inside the data itself)

c socket programming, only receiving one line at a time

You are receiving data a line at a time because it's being sent a line at a time. The fact that it ends up coming out this way is pure luck, though; TCP streams can be split up and recombined arbitrarily by the client TCP stack, or by buffering on the other end. You need some form of explicit framing in the stream -- for instance, a count sent before each line, or a \n at the end of a line.

Socket recv() receives only 1 byte of data

The problem was at the beginning of the connection when the server sends ( send() ) the first message to the client. You set the len to a number that is much larger than its actual length. It works fine in the beginning because there are no more communications, but the problem will appear when you try to send() through that socket again.

Code (integrity matters):

if(send(new_sockfd, "some words here...", 65535, 0) == -1){
perror("server: send");
}

sockets programming: sending and receiving different data to different clients in C

By using original code from geeksforgeeks and Myst comment we can solve it.

You have one server that serves on local host 127.0.0.1, and can have multiple clients for this example i assume 5 clients are enough.

Run server once, and run many client to connect seprately to that server.

Server.c

// Server side C/C++ program to demonstrate Socket programming 
#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
#define PORT 8080
#define STRING_SIZE 100
#define BUFFER_SIZE 100

int main(int argc, char const *argv[])
{

int server_fd, new_socket[5], valread;
struct sockaddr_in address;
int opt = 1;
int addrlen = sizeof(address);
char buffer[1024] = {0};

char *hello = "Hello from server";

// Creating socket file descriptor
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0)
{
perror("socket failed");
exit(EXIT_FAILURE);
}

// Forcefully attaching socket to the port 8080
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT,
&opt, sizeof(opt)))
{
perror("setsockopt");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons( PORT );

// Forcefully attaching socket to the port 8080
if (bind(server_fd, (struct sockaddr *)&address,
sizeof(address))<0)
{
perror("bind failed");
exit(EXIT_FAILURE);
}
if (listen(server_fd, 3) < 0)
{
perror("listen");
exit(EXIT_FAILURE);
}

for (int i=0;i<5;i++){
if ((new_socket[i] = accept(server_fd, (struct sockaddr *)&address,
(socklen_t*)&addrlen))<0)
{
perror("accept");
exit(EXIT_FAILURE);
}
valread = read(new_socket[i], buffer, 1024);
printf("%s\n", buffer);

char send_buf[STRING_SIZE] = "hello";
char buf[BUFFER_SIZE]={0};
sprintf(buf, "%d", i);
strcat(send_buf, buf);

send(new_socket[i], send_buf, strlen(send_buf), 0);
//printf("Hello message sent\n");

}

return 0;
}

Client.c

// Client side C/C++ program to demonstrate Socket programming 
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#define PORT 8080

int main(int argc, char const *argv[])
{
int sock = 0, valread;
struct sockaddr_in serv_addr;
char *hello = "Hello from client";
char buffer[1024] = {0};
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("\n Socket creation error \n");
return -1;
}

serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);

// Convert IPv4 and IPv6 addresses from text to binary form
if(inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr)<=0)
{
printf("\nInvalid address/ Address not supported \n");
return -1;
}

if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
{
printf("\nConnection Failed \n");
return -1;
}

send(sock , hello , strlen(hello) , 0 );
//printf("Hello message sent\n");
valread = read( sock , buffer, 1024);
printf("%s\n", buffer);

return 0;
}

Run

After compiling codes with gcc client.c -o client and gcc server.c -o server

Open one terminal for server and start server by run ./server.

Now you can connect many client [up to 5] to it by running ./client.

C socket: recv and send all data

The recv() and send() functions do not guarantee to send/recv all data (see man recv, man send)

You need to implement your own send_all() and recv_all(), something like

bool send_all(int socket, void *buffer, size_t length)
{
char *ptr = (char*) buffer;
while (length > 0)
{
int i = send(socket, ptr, length);
if (i < 1) return false;
ptr += i;
length -= i;
}
return true;
}

The following guide may help you Beej's Guide to Network Programming



Related Topics



Leave a reply



Submit