2013-08-31 40 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

相關問題