私はクライアントとサーバーにブロッキングTCPソケットを使用しています。私が読むたびに、私はまず、select
を使ってストリーム上でデータが利用可能かどうかをチェックします。私は常に40バイトずつ読み書きします。ほとんどの読み取りには数ミリ秒かそれ以下の時間がかかりますが、半分以上の時間がかかります。ソケット上で利用可能なデータがあることを知った後。非常に遅いソケット読み取りの原因は何ですか?
私もそれを引き起こしている可能性が何TCP_NODELAY
を使用していますか?
EDIT 2
私が送信され、受信した各パケットのタイムスタンプを分析し、クライアントは次のオブジェクトがサーバーによって書き込まれる前に、オブジェクトを読み取ろうとする場合にのみ、この遅延が起こることを見ました。例えば、サーバはオブジェクト番号xを書いた後、サーバはオブジェクト番号x + 1の書込みを開始する前にオブジェクトxを読み取ろうとした。これにより、サーバー側で何らかの合体が起こっていると思われます。
EDIT
サーバーは、3つの異なるポートでリッスンしています。クライアントは、これらの各ポートに1つずつ接続します。
3つの接続があります。サーバーからクライアントにデータを頻繁に送信する接続です。もう1つは、クライアントからサーバーにデータを送信するだけです。また、1バイトのデータを送信することはめったにありません。私は最初の接続の問題に直面しています。私はselect()
を使用してデータがその接続で利用可能であることを確認しています。そして、40バイトの読み取りをタイムスタンプすると、その読み取りに約0.5秒かかることがわかります。
これは、Linux上のgccを使用して
非常に参考になるプロファイルにどのようにのように任意のポインタ。
rdrr_server_start(void) {
int rr_sd; int input_sd; int ack_sd; int fp_sd;
startTcpServer(&rr_sd, remote_rr_port); startTcpServer(&input_sd, remote_input_port); startTcpServer(&ack_sd, remote_ack_port); startTcpServer(&fp_sd, remote_fp_port);
connFD_rr = getTcpConnection(rr_sd); connFD_input = getTcpConnection(input_sd); connFD_ack= getTcpConnection(ack_sd); connFD_fp=getTcpConnection(fp_sd); }
static int getTcpConnection(int sd) { socklen_t l en;
struct sockaddr_in clientAddress; len = sizeof(clientAddress); int connFD = accept(sd, (struct sockaddr*) &clientAddress, &len); nodelay(connFD); fflush(stdout); return connFD; }
static void startTcpServer(int *sd, const int port) { *sd= socket(AF_INET, SOCK_STREAM, 0); ASSERT(*sd>0);
// Set socket option so that port can be reused int enable = 1; setsockopt(*sd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int));
struct sockaddr_in a; memset(&a,0,sizeof(a)); a.sin_family = AF_INET; a.sin_port = port; a.sin_addr.s_addr = INADDR_ANY; int bindResult = bind(*sd, (struct sockaddr *) &a, sizeof(a)); ASSERT(bindResult ==0); listen(*sd,2); } static void nodelay(int fd) { int flag=1; ASSERT(setsockopt(fd, SOL_TCP, TCP_NODELAY, &flag, sizeof flag)==0); }
startTcpClient() { connFD_rr = socket(AF_INET, SOCK_STREAM, 0); connFD_input = socket(AF_INET, SOCK_STREAM, 0); connFD_ack = socket(AF_INET, SOCK_STREAM, 0); connFD_fp= socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in a; memset(&a,0,sizeof(a)); a.sin_family = AF_INET; a.sin_port = remote_rr_port; a.sin_addr.s_addr = inet_addr(remote_server_ip);
int CONNECT_TO_SERVER= connect(connFD_rr, &a, sizeof(a)); ASSERT(CONNECT_TO_SERVER==0) ;
a.sin_port = remote_input_port; CONNECT_TO_SERVER= connect(connFD_input, &a, sizeof(a)); ASSERT(CONNECT_TO_SERVER==0) ;
a.sin_port = remote_ack_port; CONNECT_TO_SERVER= connect(connFD_ack, &a, sizeof(a)); ASSERT(CONNECT_TO_SERVER==0) ;
a.sin_port = remote_fp_port; CONNECT_TO_SERVER= connect(connFD_fp, &a, sizeof(a)); ASSERT(CONNECT_TO_SERVER==0) ;
nodelay(connFD_rr); nodelay(connFD_input); nodelay(connFD_ack); nodelay(connFD_fp); }
にデータを移動する前に、TCPセグメント... – Jah
**私たちはどのようなサイズ、**サーバからクライアントに頻繁にいくつかのデータを送信しますワンについて話す? – tuxuday
おそらく、TCP_NODELAY(Nagleを無効にする)は悪い選択であり、結果として多くの短いセグメントが送信され、「論理」パケットごとに複数回のラウンドトリップが発生します。アプリケーションプログラムの側面には多くのシステムコールがあります。 – wildplasser