0

我有一个客户端和一个服务器,当客户端连接到服务器时,服务器将读取一个文本文件,将其转换为大写并逐行发送给客户端。文本文件名为“text.txt”,如下所示:

在此处输入图像描述

服务器代码

 #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;
       }

客户代码

  #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;
    }

当我运行服务器然后客户端时,我有以下响应:

在此处输入图像描述

但这不是必需的行为,我希望文本出现在文本文件中,“逐行”......那么我的代码中的问题在哪里以及如何解决它?以及为什么客户端卡在 while 循环中?

谢谢。

4

3 回答 3

1

您还需要发送换行符。getline读取所有字符直到换行,但不将换行存储在字符串中。因此,当您发送字符串时,它没有换行符。

您可以单独发送 a "\n",但最好在现有字符串中添加换行符。

例如:

  stringToUpper(STRING);
  STRING += "\n";
  ... 
于 2013-08-31T10:00:59.687 回答
1

你的程序有一些问题。他们在评论中列出的太多了,所以这就是为什么我把它们放在这里作为答案。

  • 在客户端,服务器回复存储在一个数组中,您可以使用该数组与"end"不起作用的字符串文字进行比较。将字符串转换为 astd::string或使用strcmp.
  • 客户端在 a 中有数据std::string,但仍然获取原始字符串指针并使用它来计算字符串长度,strlen而不是length使用std::string.
  • 似乎根本没有错误检查。所有套接字函数在错误时返回-1(或),并且在连接关闭时函数返回。SOCKET_ERRORrecv0
  • 您在代码中使用“幻数”,例如在客户端接收时数组的大小。不要那样做,而是(在您的客户recv调用的情况下)使用 eg sizeof(server_reply)

最重要的是:

  • TCP 套接字是一个流式套接字,这意味着没有消息边界,客户端可以在一次调用中recv实际接收到比您要求的要少,或者比在一次send调用中发送的多。这是发生在您身上的最后一件事,该recv调用实际上在一次调用中接收了从服务器发送的所有内容。而且由于您发送的字符串没有换行符,因此您收到的字符串没有换行符。

    大多数使用 TCP 套接字的协议要么在消息中包含消息长度,要么在消息中包含某种特殊的边界序列(最常见的是回车和换行符(即"\r\n")。

于 2013-08-31T10:01:52.407 回答
1

getline读取除分隔符之外的所有内容。您必须在发送之前将 LF 或 CR+LF 添加到字符串中。

于 2013-08-31T10:02:33.770 回答