1

WAN を介して 2 台のマシン間で通信できるようにするために、TCP を介したチャット プログラムを開発しています。私は C++ (Java 出身) はかなり新しく、TCP もまったく初めてなので、無理をしないでください。(: 私はかなりの量のチュートリアルを調べましたが、チャットのような機能を可能にするために長時間接続を開いたままにすることができるものは何もありません。私の現在のコードは次のようになります:

#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() を呼び出すと、エラー、具体的にはセグメンテーション違反が発生します。これは 2 番目のメッセージでのみ発生し、最初のメッセージは適切に送受信されます。

誰かが私を助けることができれば、それは大歓迎です。ありがとう!

4

1 に答える 1

0

ClientManager::message で、メソッドの最後にあるバッファを削除するのを忘れています。または、ローカル スタックでバッファを次のように宣言する必要があります。

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

そのため、バッファは呼び出しの終わりまでに自動的に割り当て解除されます。後でコードを読むと、次のようにすることをお勧めします。

char buffer[256];

msg.size() < serverReply.size の場合、サーバーの応答を読み取るためのコードがバッファー オーバーランを引き起こすと思います。たとえ 256 文字だと思っていても (メソッドの開始時にそれらを割り当てていないだけです)。このバッファ長の宣言とその後の処理には注意してください。C++ では末尾を超えて書き込むことができ、隣接する変数が破損し、segfault が発生する可能性があります。

于 2013-03-14T11:36:45.583 に答える