ソケットの受信部分をシャットダウンするには、shutdown(2)を使用できます。シャットダウンのマニュアルページを参照してください
編集:シャットダウンは、接続された(つまりTCP)ソケットでのみ機能することがわかりました。Raw ソケットには、次の 2 つの可能性があります。
- ( recvを使用して) 一時バッファーにデータを受信し、それらを (おそらく別のスレッドで) 破棄します。
- よく覚えているのですが、ソケット バッファーがいっぱいになると、受信データは自動的に破棄されます (バッファー内のデータは変更されません)。そのため、ソケット受信バッファー サイズを 0 に設定できます (後で必要に応じて大きくします)。
受信バッファ サイズを 0 に設定する方法は次のとおりです。
int opt = 0;
setsockopt(sock_fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
テスト
/**
* @file raw_print_pkt.c
* @brief
* @author Airead Fan <fgh1987168@gmail.com>
* @date 2012/08/22 12:35:22
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
int main(int argc, char *argv[])
{
int s;
ssize_t rn; /* receive number */
struct sockaddr_in saddr;
char packet[4096];
int count;
if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) < 0) {
perror("error:");
exit(EXIT_FAILURE);
}
memset(packet, 0, sizeof(packet));
socklen_t *len = (socklen_t *)sizeof(saddr);
int fromlen = sizeof(saddr);
int opt = 0;
count = 0;
while(1) {
if ((rn = recvfrom(s, (char *)&packet, sizeof(packet), 0,
(struct sockaddr *)&saddr, &fromlen)) < 0)
perror("packet receive error:");
if (rn == 0) {
printf("the peer has performed an orderly shutdown\n");
break;
}
printf("[%d] rn = %lu \n", count++, rn);
if (count == 16) {
if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt)) < 0) {
perror("setsocketopt failed");
} else {
fprintf(stdout, "setsocketopt successful\n");
}
// int shutdown(int sockfd, int how);
/* if (shutdown(s, SHUT_RD) < 0) {
* perror("shutdown failed");
* } */
}
}
return 0;
}
テスト 2 (同じ内容):
int main(int argc, char *argv[])
{
int s;
ssize_t rn; /* receive number */
char packet[4096];
int count;
if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) < 0) {
perror("error:");
exit(EXIT_FAILURE);
}
memset(packet, 0, sizeof(packet));
int opt = 0;
count = 0;
//Set recv buffer size
if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt)) < 0) {
perror("setsocketopt failed");
} else {
fprintf(stdout, "setsocketopt successful\n");
}
//10 seconds countdown
int i = 10;
while(i > 0)
{
printf("\r%d ", i);
fflush(stdout);
i--;
sleep(1);
}
printf("\n");
while(1) {
if ((rn = recv(s, (char *)&packet, sizeof(packet), 0)) <= 0)
perror("packet receive error:");
printf("[%d] rn = %lu \n", count++, rn);
}
return 0;
}
テスト 2 を続行する方法は次のとおりです。
まず、バッファ サイズを 4096 (ネットワークのトラフィックが多い場合はそれ以上) に設定します。コンパイルして起動します。データの受信を開始する前の 10 秒間に、大量のデータをソケットに送信します。10 秒後、プログラムはカウントダウン中に送信したすべてを受信します。
その後、バッファ サイズを 0 に設定します。前と同様に続行します。10 秒が経過すると、プログラムはカウントダウン中に送信したデータを受信しなくなります。しかし、recvfromにある間にデータを送信すると、正常に読み取られます。