TCP プロトコルを使用して単純なクライアント サーバー アプリケーションを作成しています。
私はデフォルトでそれを知っています。反対側がこのソケットにrecv()a を呼び出すまでブロックします。send()しかし、送信キューに ing を保持するのではなく、反対側がメッセージを編集するsend()までそれ自体をブロックし、後で反対側が複数の sによって送信された大量のメッセージを取得したことを確認することは可能ですか?recv()send()recv()send()
言い換えると。別の側を呼び出す前に、すべてsend()の側を待機させることは可能ですか?recv()send()
私の質問を説明するために。ここに簡単なコードを投稿します。
client.c
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <poll.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>
int main(int argc, char *argv[])
{
int sockfd = 0;
char sendBuff[1024];
struct sockaddr_in serv_addr;
int i;
if(argc != 2)
{
printf("\n Usage: %s <ip of server> \n",argv[0]);
return 1;
}
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("\n Error : Could not create socket \n");
return 1;
}
memset(&serv_addr, '0', sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(5000);
if(inet_pton(AF_INET, argv[1], &serv_addr.sin_addr)<=0)
{
printf("\n inet_pton error occured\n");
return 1;
}
if( connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
{
printf("\n Error : Connect Failed \n");
return 1;
}
do{
memset(sendBuff, '\0', sizeof(sendBuff));
sprintf(sendBuff, "This is line %d", i);
send(sockfd, sendBuff, strlen(sendBuff), 0);
//sleep(1);
}while(++i<100);
return 0;
}
server.c
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <time.h>
int main(int argc, char *argv[])
{
int listenfd = 0, connfd = 0;
struct sockaddr_in serv_addr;
char sendBuff[1025];
char recvBuff[100];
int i = 0;
listenfd = socket(AF_INET, SOCK_STREAM, 0);
memset(&serv_addr, '0', sizeof(serv_addr));
memset(sendBuff, '0', sizeof(sendBuff));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(5000);
bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
listen(listenfd, 10);
connfd = accept(listenfd, (struct sockaddr*)NULL, NULL);
do{
memset(recvBuff, '\0', sizeof(recvBuff));
recv(connfd, recvBuff, sizeof(recvBuff),0);
printf( "%s\n", recvBuff);
}while(++i<100);
return 0;
}
サーバー側の結果に期待するのは、次のように出力することです。
This is line 0
This is line 1
This is line 2
This is line 3
...
ただし、実際の結果は次のようになります。
This is line 0
This is line 1This is line 2This is line3This is line 4
This is line 5This is line 6This is line 7This is line 8This is line 9This is line 10
This is line 11This is line 12...
ただし、これは簡単に説明できます。クライアント側が を発行したときにsend()、サーバー側が終了するのを待たず、recv()何らかの理由で、サーバー側のrecv()ループがクライアント側の よりも遅くなりますsend()。したがってsend()、クライアント側のいくつかの が一緒に積み上げられ、サーバー全体で受信される場合があります。(私の説明は正しいですか?)
実際、非常にばかげた緩い解決策があるようです。ループ内のsleep(1)各後に(コメントアウトしたように)を追加するだけです。send()これによりコードが非常に非効率的になり、recv()ループが他の複雑なアクションを実装するのに時間がかかる場合(プログラムが大きくなると、これは明らかに予測できません)、1秒以上かかることはわかっています。このソリューションは失敗します。
では、2 つの側が相互に通信して、1 つのシングルによって送信されたメッセージが 1 つのシングルsend()によって受信されることを保証する、より確実な方法はありrecv()ますか?