문제

i have a client and a server , when the client connect to the server the server will read a text file , convert it to uppercase and send it line by line to the client . the text file is named "text.txt" and look like this:

enter image description here

server code

 #include<io.h>
 #include<iostream>
 #include <string>
 #include<fstream>
 #include<winsock2.h>
 #include<winsock2.h>


 #pragma comment(lib,"ws2_32.lib") //Winsock Library

  using namespace std;

void stringToUpper(string &s)
  {
 for(unsigned int l = 0; l < s.length(); l++)
  {
   s[l] = toupper(s[l]);
  }
  }

   int main()
  {
    WSADATA wsa;
    SOCKET s , new_socket;
     struct sockaddr_in server , client;
     int c;
    char *message;

     cout<<"\nInitialising Winsock...";
    if (WSAStartup(MAKEWORD(2,2),&wsa) != 0)
    {
       cout<<"Failed. Error Code"<<WSAGetLastError();
        return 1;
     }

   cout<<"Initialised.\n";

     //Create a socket
     if((s = socket(AF_INET , SOCK_STREAM , 0 )) == INVALID_SOCKET)
    {
        cout<<"Could not create socket "<< WSAGetLastError();
     }

      cout<<"Socket created.\n";

    //Prepare the sockaddr_in structure
      server.sin_family = AF_INET;
    server.sin_addr.s_addr = INADDR_ANY;
     server.sin_port = htons( 8888 );

    //Bind
    if( bind(s ,(struct sockaddr *)&server , sizeof(server)) == SOCKET_ERROR)
    {
      cout<<"Bind failed with error code : "<< WSAGetLastError();
       exit(EXIT_FAILURE);
  }

   puts("Bind done");

    //Listen to incoming connections
     listen(s , 3);

    //Accept and incoming connection
    puts("Waiting for incoming connections...");

     c = sizeof(struct sockaddr_in);

 while( (new_socket = accept(s , (struct sockaddr *)&client, &c)) != INVALID_SOCKET )
    {
       puts("Connection accepted");

      //Reply to the client
    string STRING;
ifstream infile;
infile.open ("text.txt");
     while(!infile.eof()) 
         {
        getline(infile,STRING); 
    stringToUpper(STRING);
        const char *STRING_mod = STRING.c_str();
        send(new_socket , STRING_mod , strlen(STRING_mod) , 0);
        }
         char *end_msg="end";
    send(new_socket , end_msg , strlen(end_msg) , 0);

   infile.close();



       }

     if (new_socket == INVALID_SOCKET)
      {
        cout<<"accept failed with error code : " << WSAGetLastError();
         return 1;
      }

       closesocket(s);
       WSACleanup();



      return 0;
       }

client code

  #include<iostream>
  #include<winsock2.h>

   #pragma comment(lib,"ws2_32.lib") //Winsock Library

   using namespace std;
 int main(int argc , char *argv[])
  {
   WSADATA wsa;
   SOCKET s;
   struct sockaddr_in server;
   char *message , server_reply[2000];
int recv_size;

   printf("\nInitialising Winsock...");
   if (WSAStartup(MAKEWORD(2,2),&wsa) != 0)
    {
    cout<<"Failed. Error Code : "<<WSAGetLastError();
    return 1;
    }

     cout<<"Initialised.\n";

    //Create a socket
      if((s = socket(AF_INET , SOCK_STREAM , 0 )) == INVALID_SOCKET)
   {
     cout<<"Could not create socket : " << WSAGetLastError();
   }

   cout<<"Socket created.\n";


   server.sin_addr.s_addr = inet_addr("127.0.0.1");
   server.sin_family = AF_INET;
   server.sin_port = htons( 8888 );

    //Connect to remote server
     if (connect(s , (struct sockaddr *)&server , sizeof(server)) < 0)
    {
       puts("connect error");
       return 1;
   }

   puts("Connected");






  recv_size = recv(s, server_reply, 2000, 0);
    server_reply[recv_size] = '\0';
    while ( server_reply != "end"){

        cout<<server_reply<<endl;
       recv_size = recv(s, server_reply, 2000, 0);
       server_reply[recv_size] = '\0';

    }






       closesocket(s);
      WSACleanup();


   return 0;
    }

when i run the server then the client , i have the following response :

enter image description here

but this is not the required behavior , i want the text appear as it looks in the text file , "line by line" ..... so where is the problem in my code and how i can fix it ? and why the client stuck at the while loop?

Thanks.

도움이 되었습니까?

해결책

You need to also send a newline. getline reads all characters until a newline, but doesn't store the newline in the string. So when you send the string, it doesn't have a newline.

You can either send a "\n" on its own, but probably better to add a newline to the existing string.

E.g. :

  stringToUpper(STRING);
  STRING += "\n";
  ... 

다른 팁

getline reads all except the delimiter. You have to add LF or CR+LF to the string before sending it.

You have a few problems with your programs. They are to many to list in a comment so that's why I put them here as an answer.

  • In the client, the server reply is stored in an array, and you use that array to compare to the string literal "end" which will not work. Either convert the string to a std::string or use strcmp.
  • The client have the data in a std::string, but still gets the raw string pointer and use that to calculate the string length using strlen instead of the length method of std::string.
  • There seems to be no error checking at all. All socket functions returns -1 (or SOCKET_ERROR) on error, and the recv function return 0 when the connection is closed.
  • You use "magic numbers" in your code, like the size of the array when receiving in the client. Don't do that, instead (in the case of your client recv calls) use e.g. sizeof(server_reply).

And most importantly of all:

  • TCP sockets is a streaming socket, that means there are no message boundaries and the client can in a single call to recv actually receive less than what you asked for, or more than was send in a single send call. It's the last thing that happens to you, the recv call actually receives all that was sent from the server in one call. And since you sent the string without newlines, you receive it without newlines.

    Most protocols using TCP sockets have either a message length included in the message, or some kind of special boundary sequence (most often carriage return and newline (i.e. "\r\n").

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top