c++ - Echo server/client message cutoff using socket send()/recv()(winsock) -


the code echo_server , echo_client posted below. noticed when type message on length in echo_client, server truncates end of , echoes part of it. buffer size 1024 bytes , message i'm typing much, shorter length. what's going on here? how solve problem server echoes complete message provided under length limit?

the server code:

#include "stdafx.h" #include <iostream> #include <string> #include <string.h>   #ifndef unicode #define unicode #endif #define win32_lean_and_mean  #include <winsock2.h> #include <ws2tcpip.h> #pragma comment(lib, "ws2_32.lib")  using namespace std;   static int maxpending = 5;   int main(int argc, char *argv[])  {  wsadata wsadata; int iresult; int optv = 0; bool connected = false; char *optval = (char*)&optv; int optlen = sizeof(optval); string q = "quit"; const char *exit =q.c_str();     iresult = wsastartup(makeword(2, 2), &wsadata); if (iresult != no_error) {     wprintf(l"wsastartup function failed error: %d\n", iresult);     return 1; }   if(argc!=2){     printf("error: incorrect number of arguments.  ");     return 1; }   socket servsock; servsock = socket(af_inet,sock_stream,ipproto_tcp); if(servsock==invalid_socket){     printf("socket function failed error: %d\n",getlasterror());     return 1; }   u_int servport = atoi(argv[1]);  sockaddr_in servaddr; servaddr.sin_family = af_inet; servaddr.sin_addr.s_addr = htonl(inaddr_any); servaddr.sin_port = htons(servport);  int opt = setsockopt(servsock,sol_socket,so_reuseaddr,optval,sizeof(optval));   if(bind(servsock,(sockaddr*)&servaddr,sizeof(servaddr))<0){     printf("bind function failed error: %d\n", getlasterror());     return 1; }    for(;;){       if(listen(servsock,maxpending) < 0){     printf("listen function failed error: %d/n",getlasterror());     return 1;     }else{         char *str = new char[5];          printf("server listening on port %d\n",servport);     }      socket clientsock;     sockaddr_in clientaddr;     socklen_t caddrlen = sizeof(clientaddr);        clientsock = accept(servsock,(sockaddr*)&clientaddr,&caddrlen);      if(clientsock < 0){        printf("accept() function failed error: %d/n", getlasterror());        goto quit;      }else if(clientsock >=0){         connected = true;     }        char cname[inet_addrstrlen];      if(inet_ntop(af_inet,&clientaddr.sin_addr,cname,sizeof(cname))!=null){         printf("handling client %s/%d\n", cname,ntohs(clientaddr.sin_port));     }else{         printf("error: unable client address");     }       char buffer[1024];       while(connected==true){            long nbytesrcvd = recv(clientsock,buffer,sizeof(buffer),0);             if(nbytesrcvd==0){             connected = false;             cout << endl;             cout << cname << ": client disconnected" << endl;                                cout << endl;             break;         }            if(nbytesrcvd < 0){             printf("error: recv() failed");             cout << endl;             goto quit;         }            if(nbytesrcvd > 0){              long nbytessent = send(clientsock,buffer,nbytesrcvd,0);             if(nbytessent < 0){                 cout << "error: send() failed" << endl;                 cout << endl;                 goto quit;                        }else if(nbytessent!=nbytesrcvd){                 cout << "send() error: sent unexpected # of bytes" << endl;                 cout << endl;                 goto quit;              }                                 }      }        quit:          int iresult = closesocket(clientsock);         if (iresult == socket_error) {             printf("closesocket function failed error: %d\n",getlasterror());         }        }     } 

and client code:

#include "stdafx.h" #include <iostream> #include <string> #include <string.h>   #ifndef unicode #define unicode #endif  #define win32_lean_and_mean  #include <windows.h> #include <winsock2.h> #include <ws2tcpip.h>   #define buffsize 1024  #pragma comment(lib, "ws2_32.lib")  using namespace std;   int main(int argc,char* argv[]) {   wsadata wsadata; int result; bool connected = false; hostent *rhost; char buffer[buffsize]; string q = "quit"; const char *exit =q.c_str();       result = wsastartup(makeword(2, 2), &wsadata); if (result != no_error) {     printf("wsastartup function failed error: %d\n", result);     return 1; }     socket connector; connector = socket(af_inet, sock_stream, ipproto_tcp); if (connector == invalid_socket) {     wprintf(l"socket function failed error: %ld\n", wsagetlasterror());     wsacleanup();     return 1; }  string hname; cout << "enter host name(url): "; cin >> hname; cout << endl;  string portnum; cout << "enter port number wish connect on: " ; cin >> portnum; cout << endl;  char *hostname = const_cast<char*>(hname.c_str()); char *hostport = const_cast<char*>(portnum.c_str());    rhost = gethostbyname(hostname); in_addr addr; addr.s_addr = *(u_long *)rhost->h_addr_list[0];    sockaddr_in clientserv; clientserv.sin_family = af_inet; clientserv.sin_addr.s_addr = addr.s_addr; clientserv.sin_port = htons(atoi(hostport));  if(connect(connector,(sockaddr*)&clientserv,sizeof(clientserv))==socket_error){     printf("connect function failed error: %d\n", getlasterror());     if(closesocket(connector)<0){         printf("closesocket function failed %d\n", getlasterror());     }     return 1; }else{     connected = true;     cout << "connected host " << hname << " on port " << portnum << endl;     cout << "type 'quit' exit program " << endl; }   while(connected==true){     int nbr = 0;    string msg;     cout << ">";    getline(cin,msg);    cout << endl;        if(msg=="quit"){         connected = false;        goto quit;    }      int len = sizeof(msg);    const char *message = msg.c_str();    strncpy_s(buffer,message,sizeof(msg));             long nbs = send(connector,buffer,len,0);    if(nbs < 0){         printf("send() failed", getlasterror());         return 1;    }     while(nbr < nbs){         nbr = recv(connector,buffer,len,0);         if(nbr < 0){             printf("recv() failed", getlasterror());             return 1;          }else if(nbr==0){             printf("recv() failed: connection closed prematurely", getlasterror());             return 1;                        }else if(nbr > 0){             string str(buffer);             cout << ">> " << str << endl;             cout << endl;         }     }    }  quit:      if (closesocket(connector) == socket_error) {         printf("closesocket function failed error: %ld\n", getlasterror());         wsacleanup();         return 1;     }   wsacleanup();  return 0; 

}

remember recv may not receive of data @ once. means recv call in server may not complete message, send gets , in turn client may receive part of sent server.

this not problem, unless receive once in client , continue doing else. do.

there 2 solutions this:

  1. make simple protocol either prepends each message message length, or have special end-of-message marker. in first case know how data there , can read in loop until received, in second case receive in aloop until end-of-message marker.

  2. make sockets non-blocking, , read in loop until recv returns error error being wsaewouldblock. there no more data read.


mistakes in client:

int len = sizeof(msg); 

this line returns size of string object, not string contained inside object. should use msg.length() length. use in couple of places.

using std::string quite okay, if use properly. e.g.:

long nbs = send(connector, msg.c_str(), msg.length(), 0); 

another thing:

nbr = recv(connector, buffer, len, 0); 

you again use wrong size here, 1 provided , erroneously use of sizeof(msg). instead should provide size of actual buffer. since buffer proper array can use e.g. sizeof(buffer) - 1 here. -1 because data send client not zero-terminated string, , need reserve space in received data terminate string:

buffer[nbr] = '\0'; 

Comments

Popular posts from this blog

Perl - how to grep a block of text from a file -

delphi - How to remove all the grips on a coolbar if I have several coolbands? -

javascript - Animating array of divs; only the final element is modified -