2012-08-02 17 views
-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; 
} 
+1

將gdb附加到服務器程序,看看發生了什麼。 – jman 2012-08-02 05:01:28

+0

除了在GDB中通過服務器或客戶端代碼進行調試外,還可以添加更多輸出。例如,如果客戶端連接成功,則可以將其打印到客戶端和服務器中的控制檯,但更重要的是,在出現_fails_和錯誤代碼時打印輸出。 – 2012-08-02 05:41:59

+1

這不是C,而是C和C++的混合。不要這樣做,這是不值得的,決定要使用哪種語言並堅持下去。 – 2012-08-02 07:08:13

回答

0

客戶並不知道要連接的服務器。 你做struct sockaddr* serverSockAddressPnt;但是這隻會將serverSockAddressPnt定義爲指向struct sockaddr的指針。但它應該被初始化或分配要連接的服務器的IP地址。

+0

OP將指針指向'&serverAddress',以便正確初始化。 – 2012-08-02 05:39:18

1

您的serverAddress變量未初始化。我沒有檢查這個,但最有可能的是serverAddress.sun_path是一個指向char,然後用隨機值初始化。這

strcpy (serverAddress.sun_path,"CServer"); 

然後覆蓋一些任意的內存。在C++做的正確方法是

struct sockaddr_un serverAddress = { 0 }; 

一般:

  • 始終,是一如既往地初始化所有變量。不要擔心效率上的一些小的改進,否則可能會帶來影響。這通常是不值得的,無論如何你還不在那裏。 (這裏用0進行正確的初始化會讓你的程序從一開始就很好地崩潰。)

  • 總是在所有警告選項上編譯。

  • 不要混合C和C++。他們有微妙的差異,這是不值得的。特別是在這裏你從使用C++中獲益匪淺。

+0

特別喜歡「從一開始就很好地碰撞」部分。 – 2012-08-02 07:30:19

+0

我想你應該看看['sockaddr_un'](http://linux.die.net/man/7/unix)結構,'sun_path'成員是一個合適的數組。 – 2012-08-02 09:00:54

1

P1。正如Joachim所建議的那樣,爲你的代碼添加更多的錯誤處理。 問題的最可能原因是你是綁定的,但在此之前,你並沒有刪除套接字文件(假設該文件已經存在,因爲你正在試驗)哪個是綁定的(即「CServer」)。

所以,即使綁定失敗,但由於錯誤是熱處理,服務器啓動(您可以通過ps命令看到它)。即使您可以看到使用ps運行的服務器,您的客戶端也無法連接。所以你可以通過在綁定之前解除連接(刪除)套接字文件來解決這個問題。

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

我希望這能解決您的問題。

共享一個鏈接的教程,我發現 http://tkhanson.net/cgit.cgi/misc.git/plain/unixdomain/Unix_domain_sockets.html

另一種看法是,你的代碼將產生殭屍(在Linux下死進程ps命令會顯示已不存在的條目),因爲你還沒有加入殭屍處理器。

我建議,臨時解決方案是pl。在服務器程序中的套接字調用之前(假設爲Linux)添加下面的行(也包括signal.h)以忽略SIGCHLD(子信號的死亡)。殭屍將不會被看到。

signal(SIGCHLD, SIG_IGN);