2013-03-12 88 views
1

我正在通過TCP開發一個聊天程序,以允許我通過WAN在兩臺機器之間進行通信。我對C++(來自Java)非常陌生,對TCP很新,所以不要太過於苛刻! (:我瀏覽了大量的教程,並繼續找到只有Echo程序,沒有任何東西可以讓連接打開很長時間以允許像功能聊天。我現在的代碼如下所示:在Ubuntu上使用C++的TCP上的聊天程序的問題12.10

#include "ClientManager.h" 

ClientManager::ClientManager() { 

} 

void ClientManager::connectCom(char* ipAdd) { 



portno = atoi(PORT); 
sockfd = socket(AF_INET, SOCK_STREAM, 0); 
if (sockfd < 0) 
    error("ERROR opening socket"); 
server = gethostbyname(ipAdd); 
if (server == NULL) { 
    fprintf(stderr,"ERROR, no such host\n"); 
    exit(0); 
} 
bzero((char *) &serv_addr, sizeof(serv_addr)); 
serv_addr.sin_family = AF_INET; 
bcopy((char *)server->h_addr, 
    (char *)&serv_addr.sin_addr.s_addr, 
    server->h_length); 
serv_addr.sin_port = htons(portno); 
if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0) 
    error("ERROR connecting"); 
} 

void ClientManager::message(std::string msg) { 
// printf("Please enter the message: "); 

char * buffer = new char[msg.size() + 1]; 
std::copy(msg.begin(), msg.end(), buffer); 
buffer[msg.size()] = '\0'; 
// bzero(buffer,256); 
// fgets(buffer,255,stdin); 
n = write(sockfd,buffer,strlen(buffer)); 
if (n < 0) 
    error("ERROR writing to socket"); 
bzero(buffer,256); 
n = read(sockfd,buffer,255); 
if (n < 0) 
    error("ERROR reading from socket"); 
printf("%s\n",buffer); 
bzero(buffer,256); 
} 

void ClientManager::closeCom() { 
close(sockfd); 
} 

void ClientManager::error(const char *msg) 
{ 
perror(msg); 
exit(0); 
} 

和我的服務器管理器看起來像這樣:

#include "ServerManager.h" 

ServerManager::ServerManager() { 
    // int sockfd, portno, n; 
//   struct sockaddr_in serv_addr; 
//  struct hostent *server; 

} 

void ServerManager::openCom() { 
char buffer[256]; 
struct sockaddr_in serv_addr, cli_addr; 
int n; 
    socklen_t clilen; 


sockfd = socket(AF_INET, SOCK_STREAM, 0); 
if (sockfd < 0) 
    error("ERROR opening socket"); 
bzero((char *) &serv_addr, sizeof(serv_addr)); 
portno = atoi(PORT); 
serv_addr.sin_family = AF_INET; 
serv_addr.sin_addr.s_addr = INADDR_ANY; 
serv_addr.sin_port = htons(portno); 
if (bind(sockfd, (struct sockaddr *) &serv_addr, 
    sizeof(serv_addr)) < 0) 
    error("ERROR on binding"); 
listen(sockfd,5); 

clilen = sizeof(cli_addr); 
newsockfd = accept(sockfd, 
      (struct sockaddr *) &cli_addr, 
      &clilen); 
if (newsockfd < 0) 
    error("ERROR on accept"); 
bzero(buffer,256); 
// n = read(newsockfd,buffer,255); 
// if (n < 0) error("ERROR reading from socket"); 
// printf("Here is the message: %s\n",buffer); 
// n = write(newsockfd,"I got your message",18); 
// if (n < 0) error("ERROR writing to socket"); 
} 

int ServerManager::readCom() { 
bzero(buffer,256); 
n = read(newsockfd,buffer,255); 
if (n < 0) error("ERROR reading from socket"); 
    printf("Here is the message: %s\n",buffer); 
n = write(newsockfd,"I got your message",18); 
if (n < 0) error("ERROR writing to socket"); 
if (buffer[0] == '0') 
    return 1; 
return 0; 
} 

void ServerManager::closeCom() { 
close(newsockfd); 
close(sockfd); 

} 

void ServerManager::error(const char *msg) { 
perror(msg); 
exit(1); 
} 

這兩個類是由誰打電話必要的功能獨立的主要功能實現我知道這些代碼本身是確定用於發送一個MESSAGE-它一直這樣做了一段時間,當客戶端調用多條消息()時,我經歷了錯誤,特別是一個分段n故障。這隻發生在第二條消息上,第一條消息被正確發送和接收。

如果有人能幫助我,這將不勝感激。謝謝!

+0

段錯誤發生時棧是什麼?您可以在gdb中運行該程序,並在崩潰時使用'where'來獲取堆棧。見http://www.cs.rochester.edu/~nelson/courses/csc_173/review/gdb.html。 – Blake 2013-03-12 20:39:00

+0

這是GDB的輸出。你是這個意思嗎? '#0 0xb7e0f884在__nss_hostname_digits_dots()從/lib/i386-linux-gnu/libc.so.6 #1 0xb7e143fd中的gethostbyname()從/lib/i386-linux-gnu/libc.so.6 # 2客戶端中的0x08048e62客戶端:: connectCom(char *)() #3 0x08048c82在main(argc = 1,argv = 0xbffff354)client.cpp:20 ' – jmarple 2013-03-12 23:38:48

回答

0

在ClientManager :: message中,您忘記了在方法結尾刪除緩衝區。 另外,您應該聲明本地堆棧,因爲這對緩衝:

char buffer[msg.size() + 1]; 

因此,緩衝區將自動被調用結束時釋放。 而閱讀後的代碼,您做的更好:

char buffer[256]; 

我覺得代碼讀取服務器的答覆會導致如果你的msg.size()< serverReply.size緩衝區溢出,即使你認爲你有256個字符(你只是沒有在方法開始時分配它們)。請注意這個緩衝區長度聲明和稍後的處理,因爲C++會讓你寫超出它的結尾,破壞相鄰變量並導致段錯誤。