2013-11-27 75 views
1

好,所以我有一個服務器&客戶端使用套接字和線程。C(Linux)中的套接字 - 我如何獲得客戶端IP和端口

服務器:

<Includes>... 


    struct sockaddr_in server; 
    int sock,rvsock; 
    int port,max,k = 0, len; 
    char buff[1024]; 
    pthread_t thr[100]; 

    void handler(int sig) 
    { 
    if(close(rvsock) < 0) 
    { 
    perror("Close."); 
    return; 
    } 
} 

void *worker (void* a) 
{ 
    k=0; 
    int ar[3]; 
    int i=0; 
    char Smax[1024]; 
    char *token; 
    recv(sock,&buff,sizeof(buff),0); 
     token = strtok(buff," "); 

     while(token && token!=" ") 

     { 
     int nr = atoi(token); 
     ar[i]=nr; 
     k=k+nr; 
     i++; 
     token = strtok(NULL," "); 
    } 
    if (k > max) 
     { 
      printf ("%d is indeed > than %d\n",k,max); 
      max=k; 
     } 

printf("Current max is %d\n",max); 
char temp[1024]; 
sprintf(temp,"%d",max); 
strcpy(Smax,"The current maximum is: "); 
strcat(Smax,temp); 
strcat(Smax," and the numbers are: "); 
for (i=0;i<3;i++) 
{ 
    sprintf(temp,"%d",ar[i]); 
    strcat(Smax,temp); 
    strcat(Smax," "); 
} 
printf ("%s\n",Smax); 
send(sock, &Smax, sizeof(Smax), 0); 
close(sock); 
} 

int main (int argc,char* argv[]) 
{ 
    int i=0; 
    if (argc < 2) 
    { 
     perror ("No port assigned."); 
     exit(0); 
} 
else 
{ 
    sscanf (argv[1],"%d",&port); 
} 
/* Creating socket (AF_INET - TCP/IP) */ 
rvsock = socket (AF_INET,SOCK_STREAM,0); 
if (rvsock<0) 
{ 
    perror("Socket was not created."); 
} 


memset(&server,0,sizeof(server)); 
server.sin_family=AF_INET; 
server.sin_addr.s_addr=INADDR_ANY; 
server.sin_port=htons(port); 

/* Binding socket */ 

if(bind(rvsock,(struct sockaddr*)&server,sizeof(server))<0) 
    perror("Error in binding socket"); 
else 
    { 
     printf("Server established.\nAwaying clients.\n"); 
    } 
/* Listening */ 

if (listen(rvsock,5)<0) 
    perror("Error in listening"); 
len = sizeof(server); 

signal(SIGINT,handler); 

/* Accepting and threading */ 

while(1 && i<100){ 
    sock = accept (rvsock,(struct sockaddr*)&server,(socklen_t * __restrict__) &len); 
    if (sock<0) 
    { 
     perror("Error in accepting socket"); 
     break; 
    } 
    pthread_create(&thr,NULL,worker,i); 
    i++; 
} 
int j; 
/* Joining threads */ 
for (j=0;j<100;j++) 
    pthread_join(thr,NULL); 
return 0; 

客戶方:

int main(int argc,char* argv[]) {

int sock; 

int k,port; 

char len[1024]; 

char buff[1024]; 


struct sockaddr_in server; 
if (argc<2) 
{ 
    perror ("Invalid number of args"); 
    exit(0); 
} 
else 
{ 
    sscanf(argv[1],"%d",&port); 
    randomize(buff); 
} 

sock = socket(AF_INET,SOCK_STREAM,0); 
if(sock<0) 
    perror("Socket creation failure"); 

memset(&server,0,sizeof(server)); 
server.sin_family=AF_INET; 
server.sin_addr.s_addr=inet_addr("127.0.0.1"); 
server.sin_port=htons(port); 

if (connect(sock,(struct sockaddr*)&server,sizeof(server))<0) 
    perror("Connection error"); 
printf("Sending input: %s\n",buff); 
send(sock,buff,sizeof(buff),0); 
while(1) 
{ 
    k = recv(sock,&len, sizeof(len),0); 
    if(k<=0) 
     break; 
    printf("Got back %s \n",len); 
} 
close(sock); 
return 0; 

服務器具有數據發送回客戶端工人功能。我需要在該數據中包含客戶端的IP和端口。

我該怎麼做?

+4

man [accept](http://linux.die.net/man/3/accept),你需要的東西存儲在addr中。 – moeCake

+1

可能重複的[如何顯示客戶端的IP地址在報告中使用c socket程序?](http://stackoverflow.com/questions/20235724/how-do-i-display-clients-ip-address-in-使用-C編程程序 - 報告 - ) – Michael

回答

2

在你的代碼在:

sock = accept (rvsock,(struct sockaddr*)&server,(socklen_t * __restrict__) &len); 

你覆蓋的server內容與客戶的信息。 len也被server中覆蓋的大小覆蓋。你需要做這樣的事情,而不是接收客戶端套接字信息(來自Beej's networking guide拍攝):

struct sockaddr_storage their_addr; 
socklen_t addr_size; 
struct addrinfo hints, *res; 
int sockfd, new_fd; 

// first, load up address structs with getaddrinfo(): 

memset(&hints, 0, sizeof hints); 
hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever 
hints.ai_socktype = SOCK_STREAM; 
hints.ai_flags = AI_PASSIVE;  // fill in my IP for me 

getaddrinfo(NULL, MYPORT, &hints, &res); 

// make a socket, bind it, and listen on it: 

sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); 
bind(sockfd, res->ai_addr, res->ai_addrlen); 
listen(sockfd, BACKLOG); 

// now accept an incoming connection: 

addr_size = sizeof their_addr; 
new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &addr_size); 

// ready to communicate on socket descriptor new_fd! 

段從man 2 accept

的論點地址是帶餡的結果參數如通信層所知,連接實體的地址。 地址參數的確切格式取決於發生通訊的域 。 address_len是一個數值結果 參數;它應該最初包含由 地址指向的空間量;在返回時,它將包含返回的地址的實際長度(以字節爲單位)。此調用與基於連接的套接字類型 一起使用,當前爲SOCK_STREAM。

相關問題