简体   繁体   English

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

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

OK so I have a server & client using sockets and threading. 好的,所以我有一个使用套接字和线程的服务器和客户端。

Server: 服务器:

   <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;

ClientSide: 客户端:

int main(int argc,char* argv[]) { 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;

The server has a worker function that sends back data to the client. 服务器具有辅助功能,可将数据发送回客户端。 I need to include in that data the IP and Port of the client. 我需要在该数据中包括客户端的IP和端口。

How can I get that ? 我该怎么办?

In your code at: 在您的代码中:

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

You're overwriting the contents of server with the client information. 您正在用客户机信息覆盖server的内容。 len is also being overwritten with the size of what was overwritten in server . len也被改写的东西是在覆盖规模server You need to do something like this instead to receive the client socket information (taken from Beej's networking guide ): 您需要执行以下操作来接收客户端套接字信息(摘自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!

Paragraph from man 2 accept : man 2 accept段落man 2 accept

The argument address is a result parameter that is filled in with the address of the connecting entity, as known to the communications layer. 参数地址是一个结果参数,该参数填充有通信层已知的连接实体的地址。 The exact format of the address parameter is determined by the domain in which the communication is occurring. 地址参数的确切格式由发生通信的域确定。 The address_len is a value-result parameter; address_len是一个值结果参数; it should initially contain the amount of space pointed to by address; 它最初应包含地址指向的空间量; on return it will contain the actual length (in bytes) of the address returned. 返回时,它将包含返回地址的实际长度(以字节为单位)。 This call is used with connection-based socket types, currently with SOCK_STREAM. 该调用与基于连接的套接字类型一起使用,当前与SOCK_STREAM一起使用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM