Comment envoyer une chaîne formatée à un socket en utilisant un petit tampon?

J’essaie d’écrire des données XML sur un socket en C. Je peux imprimer la chaîne XML à l’écran en utilisant:

printf("%d" "%s" "%s" "%d", int1, str2, str3, int4); 

Au lieu d’imprimer sur stdout, j’essaie d’ snprintf cette chaîne dans un tampon ( char[] ), puis d’écrire le contenu du tampon dans un socket. Malheureusement, j’imagine qu’ici le tampon pourrait être plein lors de l’écriture de str2 ou str3 et peut-être même pas assez gros pour contenir l’une ou l’autre chaîne.

À l’aide de snprintf il est facile de vérifier si j’ai pu écrire toutes les données dans le tampon, mais pas facile de continuer là où je me suis arrêté après avoir envoyé le contenu du tampon dans une socket.

Fondamentalement: existe-t-il une fonctionnalité qui me permettrait d’envoyer, par exemple, 64 octets à la fois "%d%s%s%d" à une socket, la chaîne formatée doit-elle être supérieure à 64 octets?

Si cette fonctionnalité n’existe pas, je voudrais savoir quelles solutions vous proposeriez (s’il y a lieu, vous pouvez supposer que les champs %s sont remplis par un robot diabolique qui tente de saturer votre tampon, quelle que soit sa taille).

Qu’en est-il de l’utilisation de fprintf avec un descripteur de socket?

Quelque chose comme:

 int sockfd = socket(AF_INET, SOCK_STREAM, 0); FILE *fd = fdopen(sockfd, "w") fprintf(fd, "%d" "%s" "%s" "%d", int1, str2, str3, int4); fflush(fd); 

Sous Linux au moins avec GNU libc, vous pouvez utiliser asprintf (3) (qui donne une chaîne de caractères malloc ) ou dprintf (3) (qui imprime dans un descripteur de fichier).

Vous pouvez aussi (et de manière plus portable) fdopen (3) le descripteur de fichier de socket, puis fprintf (3) et fflush (3) . Vous pouvez configurer la mise en mémoire tampon avec setvbuf (3) .

fileno (3) est très utile aussi …

BTW, snprintf (3) renvoie le nombre d’octets nécessaires . Donc, vous pourriez coder

 char tinybuf[100]; char* buf = tinybuf; int nbytes= snprintf(tinybuf, sizeof(tinybuf), "%s", num, ssortingng); if (nbytes >= sizeof(tinybuf)) { // rarely happens char *buf = malloc(nbytes+1); if (!buf) { perror("malloc"); abort(); }; snprintf(buf, nbytes+1, "%s", num, ssortingng); }; int off=0; while (nbytes>0) { int nbw=write(sock, buf+off, nbytes); if (nbw>0) { off += nbw; nbytes -= nbw; }; else if (nbw<0 && errno != EINTR) { perror("write"); abort(); }; }; if (buf != tinybuf) free(buf); 

Cela éviterait le malloc et serait free dans le cas habituel où le tinybuf convient ...