Reputation: 441
I am working on a client/server model. my client will write twice to the server, and in response, the server will read two times, my thought is one read - one write, however, the first read function in the server will read two write functions at one time.
server.c
int newsockfd, clilen;
struct sockaddr_in cli_addr;
char buffer[128];
int sockfd = socket(......);//socket descriptor
while (1) {
newsockfd = accept(sockfd, (struct sockaddr *)&cli_addr, &clilen);
bzero(buffer,128);
read(newsockfd, buffer, 128)//this read reads from two write functions
printf("%s: ", buffer);
bzero(buffer,128);
read(newsockfd, buffer, 128);//the return value of this read() is always 0
printf("%s\n", buffer);
}
client.c
char strres[128];
int fd = socket(.....);//client socket descriptor
while (1) {
bzero(strres,128);
snprintf(strres, sizeof(strres),"%s", "first");
write(fd,strres,strlen(strres);
bzero(strres,128);
snprintf(strres, sizeof(strres),"%s", "second");
write(fd,strres,strlen(strres); //both write write to the same read function
close(fd);
}
the output should be like "first: second", however, it is "firstsecond:" now.
Upvotes: 0
Views: 114
Reputation: 180201
I am working on a client/server model. my client will write twice to the server, and in response, the server will read two times, my thought is one read - one write, however, the first read function in the server will read two write functions at one time.
As you have discovered, it is not safe to assume that read()
s and write()
s pair up, at least not without some kind of assurance based on the underlying channel. You have in fact omitted the details that might speak to the channel details, but it looks like you are using stream-flavored sockets, which indeed do not have built-in message boundaries.
Note also that not only can one read
return the data from multiple write
s, but one read
might return only part of the data from a write
. Again: stream protocols do not have built-in message boundaries. That's one of their main characteristics.
If you want to divide the data being transferred into logical messages then you need to implement some kind of application-level protocol on top of the stream. Some simple examples would be:
Fixed-length messages. If every message is the same predetermined length (possibly including some meaningless padding bytes), then the reader can split the input into messages simply by counting bytes.
Embedded message lengths. If every message starts with a (fixed-length) count of the number of other bytes in the message, then the reader can determine from those how many bytes to read for each message
Message delimiters. If there is a byte or a byte sequence that cannot appear in any valid message, then you may use it to terminate or separate messages. The reader then uses those to split input into separate messages. Unlike the previous two examples, however, with this approach, there is no way around handling cases where a single read
obtains parts of two or more messages.
Do also bear in mind that it is not safe to assume that read
or write
always transfers the full number of bytes you specify. In addition to outright failing, both of these functions may transfer fewer bytes than specified, so you must be prepared to read
or write
again to transfer the remaining bytes, if any. The return values of calls to these functions provide information about both failures and short transfers. Do not ignore that.
Upvotes: 0
Reputation: 909
There’s nothing wrong with your code per se, this is just how sockets work. By specifying a buffer of size 128, you are telling your OS you want to read up to 128 bytes from whatever it has in buffer or wait for something to be received. Your OS just happens to have already received the two packages and hands you both. This is why most protocols are strictly question and answer. First you send package A to the server, the te server replies with a reply, then you send B, etc.
Upvotes: 1