2013-08-31 196 views
0

我有一个客户端和一个服务器,当客户端连接到服务器时,服务器将读取一个文本文件,将其转换为大写并将它逐行发送到客户。 文本文件被命名为“的text.txt”,看起来像这样:从winsock发送服务器到客户端的文本文件

enter image description here

服务器代码

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

时我运行s erver那么客户端,我有以下回应:

enter image description here

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

谢谢。

回答

1

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

您可以自己发送"\n",但可能更好地向现有字符串添加换行符。

E.g. :

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

您的程序有几个问题。他们对很多人在评论中列出,所以我就把它们放在这里作为答案。

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

而且最重要的是:

  • TCP套接字是插座,这意味着没有消息边界和客户端可以到recv一个电话竟收到比少了什么你所要求的,或多于一个send电话发送。这是发生在你身上的最后一件事情,recv电话实际上收到了全部,这是通过一次呼叫从服务器发送的。既然你发送了没有换行符的字符串,你会收到它没有换行符。

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

+0

哇,这是非常丰富的信息,我可以接受这两个答案接受这个.. ..非常感谢 – OpEtMaR

1

getline读以外的所有你必须在发送之前在字符串中添加LF或CR + LF

相关问题