簡體   English   中英

C(Linux)中的套接字-如何獲取客戶端IP和端口

[英]Sockets in C(Linux) - How do I get client IP & Port

好的,所以我有一個使用套接字和線程的服務器和客戶端。

服務器:

   <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和端口。

我該怎么辦?

在您的代碼中:

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

您正在用客戶機信息覆蓋server的內容。 len也被改寫的東西是在覆蓋規模server 您需要執行以下操作來接收客戶端套接字信息(摘自Beej的網絡指南 ):

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段落man 2 accept

參數地址是一個結果參數,該參數填充有通信層已知的連接實體的地址。 地址參數的確切格式由發生通信的域確定。 address_len是一個值結果參數; 它最初應包含地址指向的空間量; 返回時,它將包含返回地址的實際長度(以字節為單位)。 該調用與基於連接的套接字類型一起使用,當前與SOCK_STREAM一起使用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM