Socket Programmierung C/C++ - recv-Funktion hängt in Server
Ich habe Probleme bei der Nutzung von recv-Funktion
Ich eine Anwendung haben, senden Sie einige Daten aus dem client, diese Daten werden von dem server empfangen & senden Antworten, die basierend auf Daten.
Die Umsetzung funktioniert gut, wenn ich weniger als ~16 Anfragen.
Aber wenn ich senden mehr als 16 Anforderung (eines nach dem anderen) vom client die Antwort sind in Ordnung, vom server bis 16 Anfrage, aber danach ist der server hängt. Ich konnte sehen, dass die Daten übermittelt werden, vom client aber nicht empfangen vom server. Ich bin mit der Funktion recv
Ist die Rezeption geschieht in einer Schleife, die beendet nur, wenn die Kündigung request wird vom client empfangen.
Server-Code:
//Request Winsock version 2.2
fprintf(stderr,"Performing WSAStartup\n");
if ((retval = WSAStartup(0x202, &wsaData)) != 0)
{
fprintf(stderr,"FAILED with error %d\n", retval);
WSACleanup();
return -1;
}
else
{
printf("OK\n");
}
if (port == 0)
{
Usage(argv[0]);
}
/* open socket connection */
printf("Opening socket\n");
local.sin_family = AF_INET;
local.sin_addr.s_addr = (!ip_address) ? INADDR_ANY:inet_addr(ip_address);
/* Port MUST be in Network Byte Order */
local.sin_port = htons(port);
//TCP socket
listen_socket = socket(AF_INET, socket_type,0);
if (listen_socket == INVALID_SOCKET){
fprintf(stderr,"socket() failed with error %d\n", WSAGetLastError());
WSACleanup();
return -1;
}
else
{
printf("OK\n");
}
//bind() associates a local address and port combination with the socket just created.
//This is most useful when the application is a
//server that has a well-known port that clients know about in advance.
printf("Bind address and port to socket\n");
if (bind(listen_socket, (struct sockaddr*)&local, sizeof(local)) == SOCKET_ERROR)
{
fprintf(stderr,"bind() failed with error %d\n", WSAGetLastError());
WSACleanup();
return -1;
}
else
{
printf("OK\n");
}
//So far, everything we did was applicable to TCP as well as UDP.
//However, there are certain steps that do not work when the server is
//using UDP. We cannot listen() on a UDP socket.
if (socket_type != SOCK_DGRAM)
{
printf("TCP: listening on socket\n");
if (listen(listen_socket,5) == SOCKET_ERROR)
{
fprintf(stderr,"listen() failed with error %d\n", WSAGetLastError());
WSACleanup();
return -1;
}
else
{
printf("OK\n");
}
}
//Perform Applcation task
//initisations
printf("Server is listening and waiting for a connection\non port %d, protocol %s\n",port, (socket_type == SOCK_STREAM)?"TCP":"UDP");
executeServer = 1;
while(executeServer == 1)
{
fromlen =sizeof(from);
//accept() doesn't make sense on UDP, since we do not listen()
if (socket_type != SOCK_DGRAM)
{
printf("TCP: Waiting for connection (accept())\n");
msgsock = accept(listen_socket, (struct sockaddr*)&from, &fromlen);
if (msgsock == INVALID_SOCKET)
{
fprintf(stderr,"accept() error %d\n", WSAGetLastError());
WSACleanup();
return -1;
}
else
{
printf("OK\n");
printf("accepted connection from %s, port %d\n", inet_ntoa(from.sin_addr), htons(from.sin_port)) ;
}
}
else
{
msgsock = listen_socket;
}
//In the case of SOCK_STREAM, the server can do recv() and send() on
//the accepted socket and then close it.
//However, for SOCK_DGRAM (UDP), the server will do recvfrom() and sendto() in a loop.
printf("Receiving data");
if (socket_type != SOCK_DGRAM)
{
retval = recv(msgsock, Buffer, sizeof(Buffer), 0);
}
else
{
retval = recvfrom(msgsock,Buffer, sizeof(Buffer), 0, (struct sockaddr *)&from, &fromlen);
printf("Received datagram from %s\n", inet_ntoa(from.sin_addr));
}
if (retval == SOCKET_ERROR)
{
fprintf(stderr,"recv() failed: error %d\n", WSAGetLastError());
closesocket(msgsock);
return -2;
}
else
{
printf("OK\n");
}
if (retval == 0)
{
printf("Client closed connection.\n");
closesocket(msgsock);
}
else
{
printf("Received %d bytes, data \"%s\" from client\n", retval, Buffer);
}
printf("Processing Data\n");
if (!stricmp(Buffer, "exit"))
{
wsprintf(AckBuffer,"ACK");
executeServer = 0;
}
else
{
//Perform use task here based on recieved data
}
printf("Sending answer to client\n");
if (socket_type != SOCK_DGRAM)
{
retval = send(msgsock, AckBuffer, sizeof(AckBuffer), 0);
}
else
{
retval = sendto(msgsock, AckBuffer, sizeof(AckBuffer), 0, (struct sockaddr *)&from, fromlen);
}
if (retval == SOCKET_ERROR)
{
fprintf(stderr,"send() failed: error %d\n", WSAGetLastError());
}
else
{
printf("OK\n");
}
/* close TCP connection */
if (socket_type != SOCK_DGRAM)
{
closesocket(msgsock);
}
}
printf("terminating server\n");
closesocket(msgsock);
WSACleanup();
Client-Code:
fprintf(stderr,"Performing WSAStartup");
if ((retval = WSAStartup(0x202, &wsaData)) != 0)
{
fprintf(stderr,"WSAStartup() failed with error %d\n", retval);
WSACleanup();
return -1;
}
else
{
printf("OK\n");
}
if (port == 0)
{
Usage(argv[0]);
}
//Attempt to detect if we should call gethostbyname() or gethostbyaddr()
printf("Translate hastname to address -> gethostbyaddr()\n");
if (isalpha(server_name[0]))
{ //server address is a name
hp = gethostbyname(server_name);
}
else
{ //Convert nnn.nnn address to a usable one
addr = inet_addr(server_name);
hp = gethostbyaddr((char *)&addr, 4, AF_INET);
}
if (hp == NULL )
{
fprintf(stderr,"Cannot resolve address \"%s\": Error %d\n", server_name, WSAGetLastError());
WSACleanup();
exit(1);
}
else
{
printf("OK\n");
}
//Copy the resolved information into the sockaddr_in structure
printf("Opening socket\n");
memset(&server, 0, sizeof(server));
memcpy(&(server.sin_addr), hp->h_addr, hp->h_length);
server.sin_family = hp->h_addrtype;
server.sin_port = htons(port);
conn_socket = socket(AF_INET, socket_type, 0); /* Open a socket */
if (conn_socket <0 )
{
fprintf(stderr,"Error Opening socket: Error %d\n", WSAGetLastError());
WSACleanup();
return -1;
}
else
{
printf("OK\n");
}
//Notice that nothing in this code is specific to whether we
//are using UDP or TCP.
//We achieve this by using a simple trick.
// When connect() is called on a datagram socket, it does not
// actually establish the connection as a stream (TCP) socket
// would. Instead, TCP/IP establishes the remote half of the
// (LocalIPAddress, LocalPort, RemoteIP, RemotePort) mapping.
// This enables us to use send() and recv() on datagram sockets,
// instead of recvfrom() and sendto()
printf("Client connecting to: %s.\n", hp->h_name);
if (connect(conn_socket, (struct sockaddr*)&server, sizeof(server)) == SOCKET_ERROR)
{
fprintf(stderr,"connect() failed: %d\n", WSAGetLastError());
WSACleanup();
return -1;
}
else
{
printf("OK\n");
}
/* copy options string to buffer */
strcpy(Buffer,Options);
printf("Sending Data \"%s\"\n", Buffer);
retval = send(conn_socket, Buffer, sizeof(Buffer), 0);
if (retval == SOCKET_ERROR)
{
fprintf(stderr,"send() failed: error %d.\n", WSAGetLastError());
WSACleanup();
return -1;
}
else
{
printf("OK\n");
}
printf("Receiving status from server\n");
retval = recv(conn_socket, Buffer, sizeof(Buffer), 0);
if (retval == SOCKET_ERROR)
{
fprintf(stderr,"recv() failed: error %d.\n", WSAGetLastError());
closesocket(conn_socket);
WSACleanup();
return -1;
}
else
{
printf("OK\n");
}
//We are not likely to see this with UDP, since there is no
//'connection' established.
if (retval == 0)
{
printf("Client: Server closed connection.\n");
closesocket(conn_socket);
WSACleanup();
return -1;
}
printf("Received %d bytes, data \"%s\" from server.\n", retval, Buffer);
closesocket(conn_socket);
WSACleanup();
Was OS? TCP oder UDP?
Weizen: Fügen Sie den code..
Aber es ist gut zu haben, der code (im Gegensatz zu keiner), es ist nicht notwendig, um eine
printf
bei jedem Schritt, noch das "exception handling" - code in diesen if
Zweige, die nicht speziell auf deine Frage. Schneiden Sie es auf nur die Zweige, die Sie interessieren, mit einem sanity check output-sagen "Habe hier" vor die entsprechende Zeile. Ein nützliches essay zum Thema was einen guten code-Beispiele ist hier: sscce.org
InformationsquelleAutor hemanth | 2011-09-06
Du musst angemeldet sein, um einen Kommentar abzugeben.
Wenn Sie
recv
ohne dass Sie Ihre socket non-blocking-Modus, Ihrerecv
ist dabei eine richtige. Es blockiert bis es etwas zu Lesen.[UPDATE]
Vom code sind Sie in der Tat mit blockierenden socket. Ich empfehle die Verwendung von nicht-blockierenden socket, zumindest für den server. Ich glaube, Sie können einfach google wie man non-blocking socket und handle async-IO im Windows. Viel Glück!
[UPDATE2]
Zunächst Ihre server-code scheint in enger Verbindung einmal
recv
etwas liest. Da TCP nicht Versorgung Daten-Grenze, Sie können nicht einfach die Verbindung schließen. Denken Sie daran, einesend
Aufruf im client erfordert möglicherweise mehrererecv
Anrufe in server mit TCP-oder Umgekehrt.Für Ihr spezielles problem, ich bin ziemlich sicher, dass es nichts zu Lesen und das ist, warum
recv
blockiert Ihren Programm. Stellen Sie sicher, dass Ihr Kunde wirklich etwas schickt, erfolgreich.Vielen Dank für ur feedback.. ich bin neu in der socket-Programmierung Zeugs..[UPDATE2]: verbindungen werden nur geschlossen, wenn es Fehler in Empfangs-oder null-byte-Rezeption.. Der ganze Kram scheint zu funktionieren für einige 16 Befehle, und nach, dass es keine Rezeption geschieht in der server-Seite. Die client-Seite scheint in Ordnung zu sein und hat keine Fehler gemeldet, der für die übertragung für dieses scheitern Fall.
Hmm aber Sie schließen socket nach dem Versand in Ihrem server. /* schließen der TCP-Verbindung */ if (socket_type != SOCK_DGRAM) { Sie Closesocket(msgsock); }
InformationsquelleAutor young