我有一个客户端和一个服务器,当客户端连接到服务器时,服务器将读取文本文件,将其转换为大写并逐行发送到客户端。 文本文件名为“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循环?
感谢。
答案 0 :(得分:1)
您还需要发送换行符。 getline
读取所有字符直到换行符,但不将换行符存储在字符串中。因此,当您发送字符串时,它没有换行符。
您可以自行发送"\n"
,但最好在现有字符串中添加换行符。
E.g。 :
stringToUpper(STRING);
STRING += "\n";
...
答案 1 :(得分:1)
您的程序存在一些问题。他们很多人都会在评论中列出,这就是为什么我把它们放在这里作为答案。
"end"
进行比较。将字符串转换为std::string
或使用strcmp
。std::string
中的数据,但仍然获取原始字符串指针并使用该字符串指针使用strlen
而不是length
std::string
方法来计算字符串长度}}。-1
(或SOCKET_ERROR
),并且当连接关闭时recv
函数返回0
。recv
次来电的情况下)使用例如sizeof(server_reply)
。最重要的是:
TCP套接字是一个流式套接字,这意味着没有消息边界,客户端只需一次调用recv
即可获得少于您要求的内容,或者只是通过一次send
电话发送。这是您遇到的最后一件事,recv
调用实际上接收了一次调用中从服务器发送的所有。而且由于您发送的字符串没有换行符,因此您无需换行即可收到该字符串。
使用TCP套接字的大多数协议都包含消息中包含的消息长度,或者某种特殊的边界序列(最常见的是回车符和换行符(即"\r\n"
)。
答案 2 :(得分:1)
getline读取分隔符以外的所有内容。在发送之前,你必须在字符串中添加LF或CR + LF。