如何确保服务器区分在同一台计算机上从两个不同shell运行的两个不同TCP客户端?

如何确保服务器区分在同一台计算机上从两个不同shell运行的两个不同TCP客户端?,c,sockets,networking,network-programming,pthreads,C,Sockets,Networking,Network Programming,Pthreads,如果我从两个不同的shell运行客户机程序,服务器应该如何确定他当前正在与谁通话 平台:Linux,GCC 客户端代码:此客户端将主机名作为参数 #define SERVERPORT 3490 #define MAXDATASIZE 1000 int main (int argc, char *argv[]) { int clientSocketFD; int numOfBytesReceived; char

如果我从两个不同的shell运行客户机程序,服务器应该如何确定他当前正在与谁通话

平台:Linux,GCC

客户端代码:此客户端将主机名作为参数

#define SERVERPORT 3490
#define MAXDATASIZE 1000 

int main (int argc, char *argv[])
{
    int             clientSocketFD;
    int                 numOfBytesReceived;
    char                    receivedData[MAXDATASIZE];
    struct hostent                  *objHostent;
    struct sockaddr_in              serverAddress;

    if (argc != 2) 
    {
        fprintf (stderr,"usage: key in client hostname.\n");
        exit (1);
    }

    if ((objHostent = gethostbyname (argv[1])) == NULL)
    {
        herror ("error: incorrect host name specified.");
        exit (1);
    }

    if ((clientSocketFD = socket (PF_INET, SOCK_STREAM, 0)) == -1) 
    {
        perror ("error: socket system call failed.");
        exit (1);
    }

    serverAddress.sin_family = AF_INET;
    serverAddress.sin_port    = htons (SERVERPORT);
    serverAddress.sin_addr   = *((struct in_addr *)objHostent->h_addr);
    memset (serverAddress.sin_zero, '\0', sizeof serverAddress.sin_zero);

    if (connect (clientSocketFD, (struct sockaddr *)&serverAddress, sizeof serverAddress) == -1)
    {
        perror ("connect() error");
        exit (1);
    }

    while (1)
    {
        if ((numOfBytesReceived = recv (clientSocketFD, receivedData, MAXDATASIZE-1, 0)) == -1)
        {
            perror ("\nrecv() error");
        }

        receivedData [numOfBytesReceived] = '\0';

        if (send (clientSocketFD, "Get Lost", 15, 0) == -1)
        {
            perror ("send() error");
        }
    }
    close (clientSocketFD);
    return 0;
}
服务器代码:

#define SERVERPORT 3490
#define BACKLOG 10

struct threadArguments
{
    int    threadId;
    int    listeningSocketDescriptor;
    char *message;
};

struct threadArguments threadDataArray [5];

void* genericThreadFunction (void* threadData)
{
    struct threadArguments *temp;
    temp         = (struct threadArguments *) threadData;

    printf ("Hello World! It's me, thread #%ld!\n", (long) temp->threadId);

    while (1)
    {
        if (send (temp->listeningSocketDescriptor, temp->message, 14, 0) == -1)
            perror ("\nsend() error\n");

        char receivedData [14];
        int    numOfBytesReceived;
        if ((numOfBytesReceived = recv (temp->listeningSocketDescriptor, receivedData, 14-1, 0)) == -1)
        {
            perror ("\nrecv() error\n");
        }
        else
        {
            receivedData [numOfBytesReceived] = '\0';
            printf ("\nReceived: %s\n", receivedData);
        }
    }
}

int main (void)
{
    int                 serverSocketFD;
    int                 newServersocketFD;
    struct sockaddr_in          serverAddress;

    struct sockaddr_in          clientAddress;
    socklen_t           sin_size;

    if ((serverSocketFD = socket (AF_INET, SOCK_STREAM, 0)) == -1)
    {
        perror ("socket");
        exit (1);
    }
    int yes=1;
    if (setsockopt (serverSocketFD, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
    {
        perror ("setsockopt");
        exit (1);
    }

    serverAddress.sin_family     = AF_INET;                 // host byte order
    serverAddress.sin_port       = htons (SERVERPORT);      // short, network byte order
    serverAddress.sin_addr.s_addr = INADDR_ANY;             // automatically fill with my IP
    memset (serverAddress.sin_zero, '\0', sizeof serverAddress.sin_zero);

    if (bind (serverSocketFD, (struct sockaddr *)&serverAddress, sizeof serverAddress) == -1)
    {
        perror ("bind");
        exit (1);
    }

    if (listen (serverSocketFD, BACKLOG) == -1)
    {
        perror ("listen"); 
        exit (1);
    }

    pthread_t threads [5];
    int     returnValueOfPthreadCreate;
    long    threadId = -1;

    while (1) 
    {
        sin_size = sizeof clientAddress;
        if ((newServersocketFD = accept (serverSocketFD, (struct sockaddr *)&clientAddress, &sin_size)) == -1) 
        {
                perror ("accept");
                continue;
        }
        printf ("accept(): got connection from %s\n", inet_ntoa (clientAddress.sin_addr));

        threadId++;

        threadDataArray [threadId].threadId                  = threadId;
        threadDataArray [threadId].listeningSocketDescriptor = newServersocketFD;
        threadDataArray [threadId].message                   = "Excuse Me, please!";

        returnValueOfPthreadCreate = pthread_create (&threads [threadId], NULL, genericThreadFunction, (void*) &threadDataArray[threadId]);

        if (returnValueOfPthreadCreate)
        {
            printf ("ERROR; return code from pthread_create() is %d\n", returnValueOfPthreadCreate);
        }
    }

    pthread_exit (NULL);
    return 0;
}
编辑1。 Peername返回0:

if ((newServersocketFD                                                 = accept (serverSocketFD, (struct sockaddr *)&clientAddress, &sin_size)) == -1) 
        {
                perror ("accept");
                continue;
        }
        printf ("accept(): got connection from %s\n", inet_ntoa (clientAddress.sin_addr));
        printf ("\npeername: %d", getpeername (newServersocketFD, (struct sockaddr *)&clientAddress, &sin_size));

每个客户端都有一个单独的可接受套接字(
newServersocketFD

如果对每个客户端使用
getpeername()
,您会发现它们使用不同的源端口。

每个客户端都有一个单独的可接受套接字(
newServersocketFD

如果在每个端口上使用
getpeername()
,您会发现它们使用不同的源端口。

客户端的ip地址和(-)端口(如下所述)会唯一地标识客户端(-connection)

如果使用address family
If_INET
创建
listen()
ing套接字,则可以从
中类型为
struct sockaddr\u的变量中提取客户端的ip地址和(客户端连接特定的)(源)端口,该变量的引用被传递到
accept()
每次
accept()
成功返回时,使用其成员
sin\u addr
sin\u port

根据您所在的平台,您需要更改这些成员的字节顺序(有关如何执行此操作,请参阅
ntoh()
的手册页)。要将成员
sin\u addr
直接转换为字符数组,您已经在使用一种方法(
inet\u ntoa()
)来处理字节顺序


在成功的
accept()
返回的文件描述符上使用
getpeername()
(在服务器进程的上下文中,也是唯一标识客户机连接的)将返回与调用
accept()相同的对等方ip地址和端口值
did.

客户端的ip地址和(-)端口(如下所述)确实唯一地标识了客户端(-connection)

如果使用address family
If_INET
创建
listen()
ing套接字,则可以从
中类型为
struct sockaddr\u的变量中提取客户端的ip地址和(客户端连接特定的)(源)端口,该变量的引用被传递到
accept()
每次
accept()
成功返回时,使用其成员
sin\u addr
sin\u port

根据您所在的平台,您需要更改这些成员的字节顺序(有关如何执行此操作,请参阅
ntoh()
的手册页)。要将成员
sin\u addr
直接转换为字符数组,您已经在使用一种方法(
inet\u ntoa()
)来处理字节顺序


在成功的
accept()
返回的文件描述符上使用
getpeername()
(在服务器进程的上下文中,也是唯一标识客户机连接的)将返回与调用
accept()相同的对等方ip地址和端口值
确实如此。

您想以何种方式区分…?@pavun_cool我的意思是“任何”方式服务器都可以确定他当前正在与谁通话。您将为不同的客户端使用不同的文件描述符,对吧…?您的帖子的主题很容易误导,因为这不是关于客户端的创建,而是关于服务器如何区分它们。另一个(形式上误导性的)问题是
struct threadArguments
中文件描述符的命名。您所调用的
listeningSocketDescriptor
不是列表套接字,而是连接的套接字(通过列表套接字
serverSocketFD
连接
accept()
)。调用
连接的套接字
一个
接受的套接字
也可以。。。,无论如何,调用它
connected socket
更合适,因为它连接到由
connect()
…;-)返回的客户端套接字你想用哪种方式来区分…?@pavun_cool我的意思是服务器可以用“任何”方式来确定他当前正在与谁通话。你将为不同的客户端使用不同的文件描述符,对吧…?你的帖子的主题很有误导性,因为这不是关于客户端的创建,而是关于服务器如何区分它们。另一个(形式上误导性的)问题是
struct threadArguments
中文件描述符的命名。您所调用的
listeningSocketDescriptor
不是列表套接字,而是连接的套接字(通过列表套接字
serverSocketFD
连接
accept()
)。调用
连接的套接字
一个
接受的套接字
也可以。。。,无论如何,调用它
connected socket
更合适,因为它连接到由
connect()
…;-)返回的客户端套接字好吧,getpeername返回了0<代码>如果((newServersocketFD=accept(serverSocketFD,(struct sockaddr*)&clientAddress,&sin_size))=-1{perror(“accept”);continue;}printf(“accept():从%s\n获取连接”,inet_ntoa(clientAddress.sin_addr));printf(“\npeername:%d”、getpeername(newServersocketFD,(struct sockaddr*)和clientAddress以及sinu size))
@AnishaKaul:我建议您查看
getpeername()
s手册页。成功调用
accept()
已返回对等方的ip地址和源端口信息。(看我的答案)好吧,getpeername返回了0<代码>如果((newServersocketFD=accept(serverSocketFD,(struct sockaddr*)&clientAddress,&sin_size))=-1{perror(“accept”);continue;}printf(“accept():从%s\n获取连接”,inet_ntoa(clientAddress.sin_addr));printf