まず、実際にUTF-8でXAMPP上にアップロードされた日本語ファイルを、コマンドラインで表示をできるコードを示す。
ただし、アップロードされるテキストファイルの文字数によって、冒頭のヘッダ文の内容が少々変わるので、若干、テキストファイル本文の開始位置がズレる。
下記コードの newArray[i] = buf[252+i]; の252の部分をプラス2したりプラス4したりすると、おおむね、位置があう。つまり   newArray[i] = buf[254+i];  に変えると、うまくいく場合がある。（詳しくは配列の中身を解析のこと。）
252の数字の部分は、環境によって違う可能性があるので、正確には、HTTPヘッダ文字列を解析して値を決定すること。
コード例
define _WINSOCK_DEPRECATED_NO_WARNINGS // 古い関数をいくつか使っているので。古いのを置き換えできるなら不要。
// Winsock用パラメータ // 無いとコンパイル時にエラーになる。
// なぜだか、早めに宣言する必要がある。
int status;
int numsnt;
int main(int argc, char** argv) {
    // WinSockの初期化など
    WSADATA data;
    WSAStartup(MAKEWORD(2, 0), &data);
    // ポート番号
    unsigned short port = 80; // 8080 はローカルホストを意味する伝統的な番号。「9876」とかでもいい。
    // sockaddr_in 構造体の確保
    struct sockaddr_in6 destAddr;
    // sockaddr_in 構造体の設定
    memset(&destAddr, 0, sizeof(destAddr));
    destAddr.sin6_port = htons(port);
    destAddr.sin6_family = AF_INET6;
    char destIP_text[] = "::1"; // 127.0.0.1 はローカルホストを意味する番号
    inet_pton(AF_INET6, destIP_text, &destAddr.sin6_addr.s6_addr); // 下記コードからの置き換えが必要。
    // destAddr.sin_addr.s_addr = inet_addr(destIP_text); // ←これだと古くてエラーになる。
    printf("接続しようとしているIPアドレス: %s: \n", destIP_text);
    // エラー処理用などの変数
    int destSocket;
    // ソケット生成
    destSocket = socket(AF_INET6, SOCK_STREAM, 0);
    // 接続
    connect(destSocket, (struct sockaddr*)&destAddr, sizeof(destAddr));
    char SendMsg[50] = "aaaa"; // 初期化のため、なんらかの文字列が必要. MSG はメッセージのつもり 
    // printf("送ろうとするメッセージ: %s\n", SendMsg);
    // メッセージ送信
    printf("送信中...\n");
    strcpy_s(SendMsg, 50, "GET /detarame.html HTTP/1.1\r\n");
    send(destSocket, SendMsg, strlen(SendMsg), 0);
    strcpy_s(SendMsg, 50, "Host: localhost:80\r\n");
    send(destSocket, SendMsg, strlen(SendMsg), 0);
    strcpy_s(SendMsg, 50, "\r\n");
    send(destSocket, SendMsg, strlen(SendMsg), 0);
    int rVal;
    char buf[5000];
    int size = 4000;
    wchar_t wbuf[1000];
    setlocale(LC_ALL, "JPN");
    // 受信
    while (1) {
        rVal = recv(destSocket, buf, size, 0);
        if (rVal == 0 || rVal == -1 || rVal == SOCKET_ERROR) {
            break;
        }
        printf("bufもじれつ: %s\n", buf);
    }
    printf("解析中...\n");
    printf("240: %c\n", buf[240]);
    printf("241: %c\n", buf[241]);
    printf("242: %c\n", buf[242]);
    printf("243: %c\n", buf[243]);
    printf("244: %c\n", buf[244]);
    printf("245: %c\n", buf[245]); // "l" HTMLのl
    printf("246: %c\n", buf[246]);
    printf("247: %c\n", buf[247]);
    printf("248: %c\n", buf[248]);
    printf("249: %c\n", buf[249]);
    printf("250: %c\n", buf[250]);
    printf("251: %c\n", buf[251]);
    printf("252: %c\n", buf[252]);
    printf("253: %c\n", buf[253]); 
    printf("254: %c\n", buf[254]); 
    printf("255: %c\n", buf[255]); 
    printf("256: %c\n", buf[256]);
    printf("257: %c\n", buf[257]);
    printf("\n");
    printf("ヘッダ以降の文字列を新規の配列に入れています...\n");
    char newArray[100];
    for (int i = 0; i < 50; i = i + 1) {
        newArray[i] = buf[252+i];
    }
    printf("コード変換前の新配列の内容です\n");
    printf("%s\n", newArray);
    printf("\n");
    printf("ヘッダ以降の文字列を変換しています...\n");
    MultiByteToWideChar(CP_UTF8, 0, newArray, 15, wbuf, sizeof(wbuf));
    printf("受信した文字列: %ls\n", wbuf);
    printf("終\n");
    // WinSockの終了
    closesocket(destSocket);
    WSACleanup();
}
また、アップロードするテキストファイルには、
 成功
とだけ書いてあるとしよう。
実行結果
接続しようとしているIPアドレス: ::1:
送信中...
bufもじれつ: HTTP/1.1 200 OK
Date: Wed, 15 Jul 2020 05:07:28 GMT
Server: Apache/2.4.43 (Win64) OpenSSL/1.1.1f PHP/7.4.4
Last-Modified: Wed, 15 Jul 2020 04:51:36 GMT
ETag: "9-5aa73adc124aa"
Accept-Ranges: bytes
Content-Length: 9
Content-Type: text/html
・ｿ謌仙粥
解析中...
240: /
241: h
242: t
243: m
244: l
245:
246:
247:
248:
249: ・250: ｻ
251: ｿ
252: ・253: ・254: ・255: ・256: ・257: ・
ヘッダ以降の文字列を新規の配列に入れています...
コード変換前の新配列の内容です
謌仙粥
ヘッダ以降の文字列を変換しています...
受信した文字列: 成功
終
C:\Users\ユーザ名\source\repos\sockTestClient\x64\Release\sockTestClient.exe (プロセス
 4672) は、コード 0 で終了しました。
デバッグが停止したときに自動的にコンソールを閉じるには、[ツール] -> [オプション]
 -> [デバッグ] -> [デバッグの停止時に自動的にコンソールを閉じる] を有効にします
。
このウィンドウを閉じるには、任意のキーを押してください...
表示結果が長いが、ちゃんと
 受信した文字列: 成功
というふうに、アップロードした「成功」という文字列が表示されている。
解説
まず、XAMPPのアップロードの際に、UTF-8でアップロードしようが、最初に送られてくるHTTPヘッダの文字列
HTTP/1.1 200 OK
Date: Wed, 15 Jul 2020 05:07:28 GMT
Server: Apache/2.4.43 (Win64) OpenSSL/1.1.1f PHP/7.4.4
のメッセージが、XAMPPの設定にもよるが、普通はUTF-8でなく、ANSIなど別の文字コードで送られてしまうので、このヘッダ部分を、なんらかの方法で上手く除去しないといけない。
なぜなら、もしそのまま、 Windows.hにある文字コード変換の関数
 MultiByteToWideChar
を使っても、冒頭のANSI的な別コードの文字列の影響のせいで、（コンパイルはできるが）エラーになってしまい、文字列がうまく表示されないからである。
そこで、ヘッダの文字列の最後の、
 Content-Type: text/html
の文字列をなんらかの方法で探し出し、
その行の次の文字列から、新規のchar型の配列を作れば、その新規配列にはUTF-8文字列しかないので、変換の際の ANSI と UTF-8 との混在を防げる。
    printf("240: %c\n", buf[240]);
    printf("241: %c\n", buf[241]);
    printf("242: %c\n", buf[242]);
あとは、とにかく、UTF-8だけのコードさえ抜粋できてしまえば（そして、その抜粋した内容を新規の配列にまとめれば）、Windows.hにある文字コード変換の関数
 MultiByteToWideChar
を使えば、UTF-8コード（マルチバイト）を、古いWindowsでも表示できるワイド文字列に変換できるので、この MultiByteToWideChar() 関数で変換すればいいだけである。
まず、printf()関数のフォーマット指定子(%dとか%sとかのヤツ)を「%x」とすると、その変数にあるビットパターンが16進数で見れる。
recv()関数で受信した配列の中身を表示する事により、何を受信したかが明確にビットパターンで表示できる。
define _WINSOCK_DEPRECATED_NO_WARNINGS // 古い関数をいくつか使っているので。古いのを置き換えできるなら不要。
// Winsock用パラメータ // 無いとコンパイル時にエラーになる。
// なぜだか、早めに宣言する必要がある。
int status;
int numsnt;
int main(int argc, char **argv) {
  // WinSockの初期化など
  WSADATA data;
  WSAStartup(MAKEWORD(2, 0), &data);
  // ポート番号
  unsigned short port =
      80; // 8080 はローカルホストを意味する伝統的な番号。「9876」とかでもいい。
  // sockaddr_in 構造体の確保
  struct sockaddr_in6 destAddr;
  // sockaddr_in 構造体の設定
  memset(&destAddr, 0, sizeof(destAddr));
  destAddr.sin6_port = htons(port);
  destAddr.sin6_family = AF_INET6;
  char destIP_text[] = "::1"; // 127.0.0.1 はローカルホストを意味する番号
  inet_pton(AF_INET6, destIP_text,
            &destAddr.sin6_addr.s6_addr); // 下記コードからの置き換えが必要。
  // destAddr.sin_addr.s_addr = inet_addr(destIP_text); //
  // ←これだと古くてエラーになる。
  printf("接続しようとしているIPアドレス: %s: \n", destIP_text);
  // エラー処理用などの変数
  int destSocket;
  // ソケット生成
  destSocket = socket(AF_INET6, SOCK_STREAM, 0);
  // 接続
  connect(destSocket, (struct sockaddr *)&destAddr, sizeof(destAddr));
  char SendMsg[50] =
      "aaaa"; // 初期化のため、なんらかの文字列が必要. MSG はメッセージのつもり
  // printf("送ろうとするメッセージ: %s\n", SendMsg);
  // メッセージ送信
  printf("送信中...\n");
  strcpy_s(SendMsg, 50, "GET /detarame2.html HTTP/1.1\r\n");
  send(destSocket, SendMsg, strlen(SendMsg), 0);
  strcpy_s(SendMsg, 50, "Host: localhost:80\r\n");
  send(destSocket, SendMsg, strlen(SendMsg), 0);
  strcpy_s(SendMsg, 50, "\r\n");
  send(destSocket, SendMsg, strlen(SendMsg), 0);
  int rVal;
  char buf[5000];
  int size = 4000;
  wchar_t wbuf[1000];
  setlocale(LC_ALL, "JPN");
  // 受信
  while (1) {
    rVal = recv(destSocket, buf, size, 0);
    if (rVal == 0 || rVal == -1 || rVal == SOCKET_ERROR) {
      break;
    }
    printf("bufもじれつ: %s\n", buf);
  }
  printf("解析中...\n");
  for (int i = 0; i < 30; i = i + 1) {
    printf("%d: %x %c\n", 240 + i, buf[240 + i], buf[240 + i]);
  }
  printf("\n");
  printf("ヘッダ以降の文字列を新規の配列に入れています...\n");
  char newArray[100];
  for (int i = 0; i < 100; i = i + 1) {
    newArray[i] = buf[254 + i];
  }
  printf("コード変換前の新配列の内容です\n");
  printf("%s\n", newArray);
  printf("\n");
  printf("ヘッダ以降の文字列を変換しています...\n");
  MultiByteToWideChar(CP_UTF8, 0, newArray, 50, wbuf, sizeof(wbuf));
  printf("受信した文字列: %ls\n", wbuf);
  printf("終\n");
  // WinSockの終了
  closesocket(destSocket);
  WSACleanup();
}
実行結果
接続しようとしているIPアドレス: ::1:
送信中...
bufもじれつ: HTTP/1.1 200 OK
Date: Wed, 15 Jul 2020 07:59:56 GMT
Server: Apache/2.4.43 (Win64) OpenSSL/1.1.1f PHP/7.4.4
Last-Modified: Wed, 15 Jul 2020 07:58:22 GMT
ETag: "3b-5aa7649a72893"
Accept-Ranges: bytes
Content-Length: 59
Content-Type: text/html
・ｿ謌仙粥
2陦檎岼
縺・＞縺､縺､
縺輔ｓ縺弱ｇ縺・ａ
蝗・
解析中...
240: 78 x
241: 74 t
242: 2f /
243: 68 h
244: 74 t
245: 6d m
246: 6c l
247: d
248: a
249: d
250: a
251: ffffffef ・252: ffffffbb ｻ
253: ffffffbf ｿ
254: ffffffe6 ・255: ffffff88 ・256: ffffff90 ・257: ffffffe5 ・258: ffffff8a ・
259: ffffff9f ・260: d
261: a
262: 32 2
263: ffffffe8 ・264: ffffffa1 ｡
265: ffffff8c ・266: ffffffe7 ・267: ffffff9b ・268: ffffffae ｮ
269: d
ヘッダ以降の文字列を新規の配列に入れています...
コード変換前の新配列の内容です
謌仙粥
2陦檎岼
縺・＞縺､縺､
縺輔ｓ縺弱ｇ縺・ａ
蝗・
ヘッダ以降の文字列を変換しています...
受信した文字列: 成功
2行目
いいつつ
�終 ぎょうめ
C:\Users\ユーザ名\source\repos\sockTestClient\x64\Release\sockTestClient.exe (プロセス
 4756) は、コード 0 で終了しました。
デバッグが停止したときに自動的にコンソールを閉じるには、[ツール] -> [オプション]
 -> [デバッグ] -> [デバッグの停止時に自動的にコンソールを閉じる] を有効にします
。
このウィンドウを閉じるには、任意のキーを押してください...
さて、
247: d
248: a
249: d
250: a
とあるが、これは
を意味している。
さて、
251: ffffffef ・252: ffffffbb ｻ
253: ffffffbf ｿ
とあるが、
これはBOM（バイトオーダーマーク、略称BOMは「ボム」と発音）という、制御用の文字コードの一種であり、UTF-8の場合には「ef bb bf」というビットパターンがつくことがある。(詳しくはバイトオーダーマーク)
BOMがあるか無いかは、OSによって異なるが、Windowsはかつては基本的にBOMがあったが、UTF-8にはそもそもバイトオーダーは１つなので意味がなくShellBang!との親和性もなく、Windows 10 19H1以降はBOMなしが既定となった。
2024年2月時点では『メモ帳』で保存しても、BOMはつかない。
また、フリーソフトのTeraPad も、文字コード指定して保存する際に「UTF-8」を選択したとき、BOMがつく。もしTeraPadでBOMなしを選びたいなら、「UTF-8N」で保存しないといけない。
他のテキストエディタだと、「UTF-8」でもBOMなしの場合もあるので、テキストエディタの説明書などを確認のこと。
さて、BSD（マックもBSD派生）などのUnixでは、BOMをつけないのが主流である。そして、サーバ業界ではUnixが主流である。
なので、将来的にソケット関係のプログラマーはUnixの方式に合わせることになる可能性が高い。
なお、BOMなしで保存した場合でも、改行+復帰の2回ぶんの「dada」の部分は残る。
なので、もしブラウザなどを作りたい場合、手順はおおむね、
最初の「Content-type」を探し、そこに配列のポインタを合わせる。
Content-typeの次に最初に見つかった改行復帰 dada を探し、その直後に配列のポインタを合わせる。
そして、3バイトぶんの文字を読み取り、BOMであるかどうかを判定する。
BOMであれば、ポインタを3バイトすすめ、そこから文字のワイド文字への変換を始める。
BOMでなければ、そのまま文字のワイド文字の変換を始める。
のような手順になるだろう。
BOMのある場合、基本的にこのBOMの直後からテキスト本文が始まるハズなので、文字列の変換する場合には、BOM以降のビットパターンから変換していく必要がある。
誤って、BOMごと変換しようとしても、（コンパイルできても）エラーになったりして、うまく変換できない。
(※ 調査中: ) アップロードしたテキストに「いつつ」という語句があると、なぜかそこで変換エラーが起きてしまい、そこから先の文字をうまく読み取れずに、終了してしまったり、いくつかの行が読み飛ばされてしまう。