c++ - 如何用C语言将字符串从服务器返回到客户端?

标签 c++ c port stringstream

我需要将一个字符串发送回客户端,其中包括车辆的成本和带有修饰符(carStyling)的车辆。我想向客户端返回一个包含直线和成本的字符串。类似的东西;

Your Sedan Offroad will cost $150000.

下面的段落包含必要的代码。

#include <arpa/inet.h>

#include <netdb.h>

#include <netinet/in.h>

#include <unistd.h>

#include <iostream>

#include <cstring>

#include <stdlib.h>

#include <stdio.h>

#include <string>

#include <sstream>



#define MAX_MSG 100

#define LINE_ARRAY_SIZE (MAX_MSG+1)



using namespace std;



int main()

{

  int listenSocket, connectSocket, i;

  unsigned short int listenPort;

  socklen_t clientAddressLength
;

  struct sockaddr_in clientAddress, serverAddress;

  char line[LINE_ARRAY_SIZE];





  cout << "Enter port number to listen on (between 1500 and 65000): ";

  cin >> listenPort;



  // Create socket for listening for client connection

  // requests.

  listenSocket = socket(AF_INET, SOCK_STREAM, 0);

  if (listenSocket < 0) {

    cerr << "cannot create listen socket";

    exit(1);

  }



  // Bind listen socket to listen port. First set various

  // fields in the serverAddress structure, then call

  // bind().



  // htonl() and htons() convert long integers and short

  // integers (respectively) from host byte order (on x86

  // this is Least Significant Byte first) to network byte

  // order (Most Significant Byte first).

  serverAddress.sin_family = AF_INET;

  serverAddress.sin_addr.s_addr = htonl(INADDR_ANY);

  serverAddress.sin_port = htons(listenPort);



  if (bind(listenSocket,

           (struct sockaddr *) &serverAddress,

           sizeof(serverAddress)) < 0) {

    cerr << "cannot bind socket";

    exit(1);

  }



  // Wait for connections from clients. This is a

  // non-blocking call; i.e., it registers this program with

  // the system as expecting connections on this socket, and

  // then this thread of execution continues on.

  listen(listenSocket, 5);



  while (1) {

    cout << "Waiting for TCP connection on port " << listenPort << " ...\n";



    // Accept a connection with a client that is requesting

    // one. The accept() call is a blocking call; i.e., this

    // thread of execution stops until a connection comes

    // in. connectSocket is a new socket that the system

    // provides, separate from listenSocket. We *could*

    // accept more connections on listenSocket, before

    // connectSocket is closed, but this program doesn't do

    // that.

    clientAddressLength = sizeof(clientAddress);

    connectSocket = accept(listenSocket,

                           (struct sockaddr *) &clientAddress,

                           &clientAddressLength);

    if (connectSocket < 0) {

      cerr << "cannot accept connection ";

      exit(1);

    }



    // Show the IP address of the client.

    // inet_ntoa() converts an IP address from binary form to the

    // standard "numbers and dots" notation.

    cout << "  connected to " << inet_ntoa(clientAddress.sin_addr);



    // Show the client's port number.

    // ntohs() converts a short int from network byte order (which is

    // Most Significant Byte first) to host byte order (which on x86,

    // for example, is Least Significant Byte first).

    cout << ":" << ntohs(clientAddress.sin_port) << "\n";



    // Read lines from socket, using recv(), storing them in the line

    // array.  If no messages are currently available, recv() blocks

    // until one arrives.

    // First set line to all zeroes, so we'll know where the end of

    // the string is.

    memset(line, 0x0, LINE_ARRAY_SIZE);



    while (recv(connectSocket, line, MAX_MSG, 0) > 0) {

      cout << "  --  " << line << "\n";



      // Convert line to upper case.

      for (i = 0; line[i] != '\0'; i++)

        line[i] = toupper(line[i]);





      // creating an object to direct line to a string array

      std::string delimiter[2];

      int i = 0;

      double cost = 0;

      std::string carType;

      std::string carStyling;

      std::string sline;

      sline = line;

      stringstream ssin(sline);



          while (ssin.good() && i < 2){

            ssin >> delimiter[i];

            ++i;

      }

          for(i = 0; i < 2; i++){

            cout << delimiter[i] << endl;

      }



          if(i==0) {

            carType = delimiter[0];



              if(carType.compare("SEDAN")==0){

                sline = "Your Sedan";

                cost = 100000;

                std::copy(sline.begin(), sline.end(), line);

                line[sline.size()] = '\0';

              }

              else if(carType.compare("MPV")==0){

                sline = "MPV";

                cost = 120000;

                std::copy(sline.begin(), sline.end(), line);

                line[sline.size()] = '\0';

              }

              else if(carType.compare("SUV")==0){

                sline = "SUV";

                cost = 140000;

                std::copy(sline.begin(), sline.end(), line);

                line[sline.size()] = '\0';

              }

              else if(carType.compare("LUXURY")==0){

                sline = "LUXURY";

                cost = 180000;

                std::copy(sline.begin(), sline.end(), line);

                line[sline.size()] = '\0';

              }



         if(i==2) {

            carStyling = delimiter[1];



              if(carStyling.compare("SPORTY")==0){

                sline += "Sporty";

                cost = cost * 1.5;

              }

              else if(carStyling.compare("OFFROAD")==0){

                sline += "Offroad";

                cost = cost * 1.3;

              }



        }



      }





      // Send converted line back to client.

      if (send(connectSocket, line, strlen(line) + 1, 0) < 0)

        cerr << "Error: cannot send modified data";



      memset(line, 0x0, LINE_ARRAY_SIZE);  // set line to all zeroes

    }

  }

}

这里的另一个是 client.cc 的代码

#include <netdb.h>

#include <netinet/in.h>

#include <unistd.h>

#include <iostream>

#include <cstring>

#include <stdlib.h>



#define MAX_LINE 100

#define LINE_ARRAY_SIZE (MAX_LINE+1)



using namespace std;



int main()

{

  int socketDescriptor;

  unsigned short int serverPort;

  struct sockaddr_in serverAddress;

  struct hostent *hostInfo;

  char buf[LINE_ARRAY_SIZE], c;



  cout << "Enter server host name or IP address: ";

  cin.get(buf, MAX_LINE, '\n');



  // gethostbyname() takes a host name or ip address in "numbers and

  // dots" notation, and returns a pointer to a hostent structure,

  // which we'll need later.  It's not important for us what this

  // structure is actually composed of.

  hostInfo = gethostbyname(buf);

  if (hostInfo == NULL) {

    cout << "problem interpreting host: " << buf << "\n";

    exit(1);

  }



  cout << "Enter server port number: ";

  cin >> serverPort;

  cin.get(c); // dispose of the newline



  // Create a socket.  "AF_INET" means it will use the IPv4 protocol.

  // "SOCK_STREAM" means it will be a reliable connection (i.e., TCP;

  // for UDP use SOCK_DGRAM), and I'm not sure what the 0 for the last

  // parameter means, but it seems to work.

  socketDescriptor = socket(AF_INET, SOCK_STREAM, 0);

  if (socketDescriptor < 0) {

    cerr << "cannot create socket\n";

    exit(1);

  }



  // Connect to server.  First we have to set some fields in the

  // serverAddress structure.  The system will assign me an arbitrary

  // local port that is not in use.

  serverAddress.sin_family = hostInfo->h_addrtype;

  memcpy((char *) &serverAddress.sin_addr.s_addr,

         hostInfo->h_addr_list[0], hostInfo->h_length);

  serverAddress.sin_port = htons(serverPort);



  if (connect(socketDescriptor,

              (struct sockaddr *) &serverAddress,

              sizeof(serverAddress)) < 0) {

    cerr << "cannot connect\n";

    exit(1);

  }



  cout << "\nWelcome to Car Customization Server. What are your orders?\n";

  cout << ">> Type of vehicle: Sedan, MPV, SUV, Luxury\n";

  cout << ">> Type of Styling: Sporty, Offroad\n";

  cout << ">> Eg. To order type: MPV Sporty\n";



  // Prompt the user for input, then read in the input, up to MAX_LINE

  // charactars, and then dispose of the rest of the line, including

  // the newline character.

  cout << "Enter Order: ";

  cin.get(buf, MAX_LINE, '\n');

  while (cin.get(c) && c != '\n') 

    ; //Loop does nothing except consume the spare bytes





  // Stop when the user inputs a line with just a dot.

  while (strcmp(buf, ".")) { //strcmp returns 0 when the two strings

                 //are the same, so this continues when

                 //they are different

    // Send the line to the server.

    if (send(socketDescriptor, buf, strlen(buf) + 1, 0) < 0) {

      cerr << "cannot send data ";

      close(socketDescriptor); //Note this is just like using files...

      exit(1);

    }



    // Zero out the buffer.

    memset(buf, 0x0, LINE_ARRAY_SIZE);



    // Read the modified line back from the server.

    if (recv(socketDescriptor, buf, MAX_LINE, 0) < 0) {

      cerr << "didn't get response from server?";

      close(socketDescriptor);

      exit(1);

    }



    cout << "results: " << buf << "\n";



    // Prompt the user for input, then read in the input, up to MAX_LINE

    // charactars, and then dispose of the rest of the line, including

    // the newline character.  As above.

    cout << "Enter Order: ";

    cin.get(buf, MAX_LINE, '\n');

    while (cin.get(c) && c != '\n')

      ; //again, consuming spare bytes

  }



  close(socketDescriptor);

  return 0;

}

所以,如果有人知道如何发回字符串和成本。请回复。谢谢。

最佳答案

您可以通过复制字节将 std::string sline 打包到发送缓冲区中:

memcpy(line, sline.c_str(), strlen(sline.c_str()))

发送它,然后在客户端以同样的方式解压它。

编辑: 为您的服务器尝试以下代码,这是您想要的吗?

#include <arpa/inet.h> 
#include <netdb.h> 
#include <netinet/in.h> 
#include <unistd.h> 
#include <iostream> 
#include <cstring> 
#include <stdlib.h> 
#include <stdio.h> 
#include <string> 
#include <sstream> 

#define MAX_MSG 100 
#define LINE_ARRAY_SIZE (MAX_MSG+1) 

using namespace std; 

int main() 
{ 
  int listenSocket, connectSocket, i; 
  unsigned short int listenPort; 
  socklen_t clientAddressLength; 
  struct sockaddr_in clientAddress, serverAddress; 
  char line[LINE_ARRAY_SIZE]; 

  cout << "Enter port number to listen on (between 1500 and 65000): "; 
  cin >> listenPort; 

  listenSocket = socket(AF_INET, SOCK_STREAM, 0); 

  if (listenSocket < 0) { 
    cerr << "cannot create listen socket"; 
    exit(1); 
  } 

  serverAddress.sin_family = AF_INET; 
  serverAddress.sin_addr.s_addr = htonl(INADDR_ANY); 
  serverAddress.sin_port = htons(listenPort); 

  if (bind(listenSocket, (struct sockaddr *) &serverAddress, 
           sizeof(serverAddress)) < 0) { 
    cerr << "cannot bind socket"; 
    exit(1); 
  } 

  listen(listenSocket, 5); 

  while (1) { 
    cout << "Waiting for TCP connection on port " << listenPort << " ...\n"; 
    clientAddressLength = sizeof(clientAddress); 
    connectSocket = accept(listenSocket, (struct sockaddr *) &clientAddress, 
                           &clientAddressLength); 

    if (connectSocket < 0) { 
      cerr << "cannot accept connection "; 
      exit(1); 
    } 
    cout << "  connected to " << inet_ntoa(clientAddress.sin_addr); 
    cout << ":" << ntohs(clientAddress.sin_port) << "\n"; 

    memset(line, 0x0, LINE_ARRAY_SIZE); 
    while (recv(connectSocket,line, MAX_MSG, 0) > 0) { 

    cout << "  --  " << line << "\n"; 

    std::string delimiter[2]; 
    int i = 0; 
    double cost = 0; 
    std::string carType; 
    std::string carStyling; 
    std::string sline; 
    sline = line; 
    stringstream ssin(sline); 

    while (ssin.good() && i < 2){ 
      ssin >> delimiter[i]; 
      ++i; 
    } 
    sline = ""; 

    for(i = 0; i < 2; i++){ 
      cout << delimiter[i] << endl; 
    } 
    sline += "Your "; 
    carType = delimiter[0]; 

    if(carType.compare("Sedan")==0){ 
      sline += "Sedan"; 
      cost = 100000; 
    } 
    else if(carType.compare("MPV")==0){ 
      sline += "MPV"; 
      cost = 120000; 
    } 
    else if(carType.compare("SUV")==0){ 
      sline += "SUV"; 
      cost = 140000; 
    } 
    else if(carType.compare("Luxury")==0){ 
      sline += "Luxury"; 
      cost = 180000; 
    } 

    carStyling = delimiter[1]; 

    if(carStyling.compare("Sporty")==0){ 
      sline += " Sporty "; 
      cost = cost * 1.5; 
    } 

    else if(carStyling.compare("Offroad")==0){ 
      sline += " Offroad "; 
      cost = cost * 1.3; 
    } 

    sline += "will cost "; 
    std::ostringstream ss; 
    ss << cost; 
    sline += ss.str(); 

    sline.copy(line, sline.length()); 

    if (send(connectSocket, line, strlen(line) + 1, 0) < 0) 
      cerr << "Error: cannot send modified data"; 
      memset(line, 0x0, LINE_ARRAY_SIZE);  // set line to all zeroes 
    } 
  } 
}

关于c++ - 如何用C语言将字符串从服务器返回到客户端?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46599358/

相关文章:

python - 如何将其从Python转换为C?

c - 自动错误报告工具 (ABRT) 如何工作以便在运行时捕获核心?

node.js - 通过端口 80 上的 PM2 运行 Node 应用程序

go - Go语言中的Mach ports和Channel有什么关系?

c++ - 在C++中模仿OpenCL float2类型

c++ - 从文本存储访问 C++ 函数

c - 如果值包含 '&' 字符,则解析 POST 请求

c - 在无限循环中通过套接字进行客户端服务器通信

c++ - 函数模板和模棱两可的模板参数

c++ - 调用 ConnectNamedPipe 时出现 ERROR_INVALID_HANDLE