[M1 Mac, Big Sur 11.6.8, clang 13.0.0, NO IDE]
『C言語によるTCP/IPネットワークプログラミング』サンプルコード読解の続きです。ここら辺になってくると土台にある知見が膨大なので端折りながら理解に努めます。
受信データのヘッダ部は標準出力し、データ部は同名のファイルとして保存します。
それぞれのデータサイズ算出のため下図にポインタの関係をまとめました。
int SOCrecvDataToFile(int soc, const char *filename)
{
int width;
struct timeval timeout; // 時刻
fd_set readOK; // FD(ファイルディスクリプタ)
// fd_set mask;
char tmpbuf[8193]; // 8192 = 2^13
char *ptr;
int size;
int end;
int head;
FILE *fp;
if((fp = fopen(filename, "w")) == NULL){
perror("fopen");
return(-1);
}
FD_ZERO(&readOK); // FD初期化
FD_SET(soc,&readOK); // FDセット
width = soc + 1;
head =0 ;
end = 0;
while(1){
timeout.tv_sec = 1;
timeout.tv_usec = 0;
// readOK = mask;
// FDを監視
switch(select(width, &readOK, NULL, NULL ,&timeout)){
case -1:
if(errno!=EINTR){
perror("select");
end=1;
}
break;
case 0:
break;
default:
if(FD_ISSET(soc, &readOK)){ // FDを判別
size = recv(soc, tmpbuf, 8192, 0); // データ受信
if(size <= 0){
end = 1;
}
else{
if(head == 0){
ptr = memstr(tmpbuf, size, "\r\n\r\n", 4); // バイナリ検索
if(ptr != NULL){
// ヘッダ部
fwrite(tmpbuf, ptr-tmpbuf + 4, 1, stdout);
head=1;
// データ部
fwrite(ptr + 4,size-(ptr-tmpbuf)-4,1,fp);
}
else{
// ヘッダ部
fwrite(tmpbuf, size, 1, stdout);
}
}
else{
// データ部
fwrite(tmpbuf, size, 1, fp);
}
}
}
break;
}
if(end==1){
break;
}
}
fclose(fp);
return(0);
}