如何从C中返回一个字符串从服务器到客户端?
我需要发送一个字符串回客户端,其中包括车辆和车辆的修改器(carStyling)的成本。我想返回一个包含sline和客户端成本的字符串。就像是;如何从C中返回一个字符串从服务器到客户端?
您的轿车越野将花费$ 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
}
}
}
为什么在'sline.length()'提供长度时使用'strlen'?这个额外的'memcpy'不需要,因为你可以直接在'send'的调用中使用'sline.c_str()'。 –
你是对的,但是如果他想把“字符串和成本”作为一个发送。也许最好的办法是找出一些发送协议。例如,打包到传入字符串的缓冲区长度,然后字符串,然后四个字节int为成本。然后在另一边解开它。 –
@PawełDymowski谢谢你。我现在就试试看。 –
由于使用C++构造,它无法编译为C。你为什么要标记它?另外:你的问题到底是什么? “如何做X?”似乎太宽泛。 –
尽管使用单个空行将代码分段为段落很好,但您在另一个方向上走了很远。你展示的代码是否真正复制粘贴? –
@AlgirdasPreidžius这是两者的结合。 –