Je développe une application client/serveur qui partage des images de caméra. Le cycle général est:Winsock: Comment arrêter l'envoi/la réception sans fermer la connexion
- Le client capture une image de caméra et la compresse en une image binaire. Après cela, il l'envoie au serveur
- Le serveur connaît exactement la taille du tampon (640 * 480/8 octets), ce qui lui permet de recevoir l'image du trou avec un seul appel recv. Le prochain appel recv obtiendra la deuxième image et ainsi de suite
- Après avoir reçu l'image, le serveur travaille avec l'image et enverra ensuite une autre image au client. Mais voici le problème: L'image est compressée en JPEG et donc le client ne connaît pas la taille du fichier et ne peut pas recevoir l'image comme le serveur avec une longueur de buffer fixe.
Je pense que ce ne serait pas un problème si le serveur fermait la connexion après l'envoi de l'image. Mais je ne veux pas fermer la connexion parce que dans le cycle suivant, je vais envoyer l'image suivante sur la même connexion.
Ma question est: Comment puis-je dire au client que le serveur envoie l'image du trou sans fermer la connexion?
Voici quelques code: (Le client envoie l'image binaire au serveur)
void sendToServer(char* sendbuf, int sendbuflen) {
int iResult = send(ConnectSocket, sendbuf, sendbuflen, 0);
if (iResult == SOCKET_ERROR) {
(*errCallbackFunc)("Sending image error", -1);
}
}
(Le serveur reçoit l'image avec une seule functioncall - recbuflen = 640 * 480/8)
int receiveCameraImages(ARUint8* dataPtr) {
int iResult;
iResult = recv(ClientSocket, recvbuf, recvbuflen, 0);
if (iResult > 0) {
if ((*(recvbuf+0)) != 'U' || (*(recvbuf+((xsize*ysize/8)-1))) != 'U')
return RECEIVING_INCOMPLETE;
convertBWChartoBGR(recvbuf, dataPtr, recvbuflen);
return RECEIVING_SUCCEEDED;
} else if (iResult == 0) {
(*errCallbackFunc)("Connection closing", -1);
return RECEIVING_CONN_CLOSED;
}
else {
(*errCallbackFunc)("recv failed", WSAGetLastError());
return RECEIVING_ERROR;
}
}
(maintenant, le serveur fonctionne avec l'image et envoyer une autre jpeg image compressée retour)
int sendObjectImage(ARUint8* dataPtr, int bufLen) {
int iResult;
/* send the openGLBuffer back to the client */
iResult = send(ClientSocket, dataPtr, bufLen, 0);
if (iResult == SOCKET_ERROR) (*errCallbackFunc)("send openglbuffer back to client failed", WSAGetLastError());
}
(Et le client ne sait pas la taille de la mémoire tampon est donc il reçoit des parties 512Byte)
int receiveFromServer(ARUint8* dataPtr) {
int iResult, returnBufLen = 0;
int recvBufLen = DEFAULT_BUFFER_LEN;
ARUint8 recvBuf[DEFAULT_BUFFER_LEN];
/* receive openGL buffer */
do {
iResult = recv(ConnectSocket, recvBuf, recvBufLen, 0);
if (iResult > 0) {
printf("Bytes received: %d\n", iResult);
returnBufLen += iResult;
}
else if (iResult == 0)
printf("Connection closed\n");
else
printf("recv failed: %d\n", WSAGetLastError());
} while (iResult >= DEFAULT_BUFFER_LEN);
dataPtr = recvBuf;
return returnBufLen;
}
avec le temps (iResult> = DEFAULT_BUFFER_LEN) Je pensais qu'il arrête la réception (parce que si une partie est plus petit que 512Bytes il doit être la fin). Mais mon recvBuf ne contient que les derniers octets.
Peut-être qu'il est possible que je ne comprenne pas les trucs de trous winsock, mais je pensais que le recvBuf contiendra le tampon de trou que j'ai reçu. Est-ce faux? Comment puis-je obtenir le buffer reçu sans fermer la connexion?
Ok c'est un essai. Mais comment puis-je obtenir le tampon de trou après avoir appelé recv plusieurs fois?Sur mon site client, j'appelle recv plusieurs fois mais si je quitte la boucle, il n'y a que les octets de mon dernier appel recv dans le buffer. – ben
@ben: Lorsque vous appelez 'recv()' plusieurs fois avec le même tampon, vous lui demandez d'écraser ce tampon avec les nouvelles données. Donc, appelez-le avec un tampon différent, une adresse plus récente dans le même tampon ou copiez d'abord les données dans le tampon. – caf
@caf: merci pour cela. Je me demande pourquoi je n'ai pas encore trouvé d'exemple pour cela, cela semble être un problème courant. – ben