-1

すでにサーバーをバックグラウンドで実行しようとしていて、ps の下に表示されています。サーバーが実行されているのを確認できますが、クライアントを実行しようとすると、サーバーはクライアントに「サーバーに正常に接続されました」と書き込む必要がありますが、そこには何も出力されません。

私のサーバーコード

#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/un.h>
#include <sys/types.h>
#include <sys/socket.h>

#ifndef AF_LOCAL
#define AF_LOCAL AF_UNIX
#endif
#ifndef PF_LOCAL
#define PF_LOCAL PF_UNIX
#endif

using namespace std;

int main()
{

int serverFd;
int clientFd;
int serverLen;
int clientLen;
string message;
string serverSockAddrPtr;
struct sockaddr* serverSockAddressPnt;
struct sockaddr* clientSockAddressPnt;
struct sockaddr_un serverAddress;
struct sockaddr_un clientAddress;

cout << "" << endl;
cout << "Running server program 'css' ...... " << endl;
cout << "" << endl;


// SOCKET CREATION PART - SERVER
serverFd = socket (AF_LOCAL, SOCK_STREAM, 0);

/* Set domain type */
serverAddress.sun_family = AF_LOCAL;

/* Set name */
strcpy (serverAddress.sun_path, "CServer");


/* GET SIZE OF Server Addres */
serverLen = sizeof serverAddress;
/* GET SIZE OF Client Addres */
clientLen = sizeof clientAddress;

/* Get Server Sock Address Pointer*/
serverSockAddressPnt = (struct sockaddr *) &serverAddress;
/* Get Client Sock Address Pointer*/
clientSockAddressPnt = (struct sockaddr *) &clientAddress;

/* Create file */
bind (serverFd, serverSockAddressPnt , serverLen);

/* listen for connection */
listen (serverFd,5);


cout << "" << endl;
// SOCKET CREATION END - SERVER


while(1)
{
//accept client connection
clientFd = accept(serverFd, clientSockAddressPnt, (socklen_t*)&clientLen);

if(clientFd >= 0)
{
    if(fork() == 0)
    {
        message="Successfully connected to the server";
        write(clientFd,message.c_str(),strlen(message.c_str())+1);
        close(clientFd);
        exit(0);
    }
    else
        close(clientFd);
}

}

return 0;
}

私のクライアントコード

#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/un.h>
#include <sys/types.h>
#include <sys/socket.h>
#define DEFAULT_PROTOCOL 0
#ifndef AF_LOCAL
#define AF_LOCAL AF_UNIX
#endif
#ifndef PF_LOCAL
#define PF_LOCAL PF_UNIX
#endif

using namespace std;

/* READ LINE FUNCTION*/
int readLine (int fd,char* str)
{
    int n;
    do
    {
        n = read(fd,str,1);
    }while(n>0&& *str++ != 0);
    return(n>0);
}
/* READ LINE FUNCTION END*/


/* READ SERVER FUNCTION*/
void readServer (int fd)
{
    char str[500];
    while (readLine(fd,str))
    {
        printf("%s",str);
    }
}
/* READ SERVER FUNCTION END*/




int main()
{

int clientFd,serverLen,result;
struct sockaddr_un serverAddress;
struct sockaddr* serverSockAddressPnt;

/* Get Server Sock Address Pointer*/
serverSockAddressPnt = (struct sockaddr *) &serverAddress;

/* GET SIZE OF Server Addres */
serverLen = sizeof serverAddress;

clientFd = socket (AF_LOCAL, SOCK_STREAM, DEFAULT_PROTOCOL);
serverAddress.sun_family = AF_LOCAL;
strcpy (serverAddress.sun_path,"CServer");

do
{
    // a loop to keep trying till connected.
    result=connect(clientFd,serverSockAddressPnt,serverLen);
    if(result==-1)
    {
        //wait for 1 second to retry
        sleep(1);
    }

}while(result==-1);
readServer (clientFd);
close (clientFd);
exit(0);

return 0;
}
4

3 に答える 3

1

serverAddress変数が初期化されていません。私はこれをチェックしませんでしたが、おそらくserverAddress.sun_pathへのポインターcharであり、ランダムな値で初期化されます。これ

strcpy (serverAddress.sun_path,"CServer");

次に、任意のメモリを上書きします。Cでこれを行う正しい方法は次のとおりです

struct sockaddr_un serverAddress = { 0 };

一般的:

  • 常に、はい常に、すべての変数を初期化します。そうしないと、効率が多少向上する可能性がありますが、心配する必要はありません。それは通常価値がなく、いずれにせよあなたはまだそこにいません。(ここで適切な初期化を0行うと、プログラムは最初からうまくクラッシュします。)

  • 常にすべての警告オプションをオンにしてコンパイルします。

  • C と C++ を混在させないでください。それらには、価値のない微妙な違いがあります。特にここでは、C++ を使用しても何も得られません。

于 2012-08-02T07:18:14.137 に答える
1

Pl。Joachimが提案したように、コードにエラー処理を追加してください。問題の原因として最も可能性が高いのは、バインドしていることですが、その前に、バインドされるソケット ファイル (実験中のため、ファイルが既に存在すると仮定します) (つまり、「CServer」) を削除していません。

したがって、bind が失敗しても、エラーはホット ハンドリングされるため、サーバーは起動します (ps コマンドで確認できます)。また、psを使用してサーバーが実行されていることを確認できても、クライアントは接続できません。したがって、バインドする前にソケット ファイルをリンク解除 (削除) することで、これを解決できます。

unlink("CServer");
bind (serverFd, serverSockAddressPnt , serverLen);

これで問題が解決することを願っています。

私が見つけたチュートリアルのリンクを共有します http://tkhanson.net/cgit.cgi/misc.git/plain/unixdomain/Unix_domain_sockets.html

もう 1 つの観察結果は、ゾンビ ハンドラーを追加していないため、コードがゾンビを生成することです (Linux では、無効なプロセスの ps コマンドで無効なエントリが表示されます)。

私が提案する一時的な解決策は、そのplです。SIGCHLD (子シグナルの死) を無視するために、サーバー プログラムでソケット呼び出しの前に (Linux を想定して) 以下の行を追加します (signal.h も含めます)。ゾンビは表示されません。

signal(SIGCHLD, SIG_IGN);
于 2012-08-02T07:52:34.797 に答える
0

クライアントは、接続するサーバーを認識していません。あなたはしますが、これはへのポインタとしてstruct sockaddr* serverSockAddressPnt;のみ定義されます。ただし、接続するサーバーのIPアドレスが初期化または割り当てられることになっています。serverSockAddressPntstruct sockaddr

于 2012-08-02T05:06:57.083 に答える