【发布时间】:2012-01-07 09:12:07
【问题描述】:
如果我从两个不同的 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));
【问题讨论】:
-
你想以哪种方式区分...?
-
@pavun_cool 我的意思是服务器能够确定他当前正在与谁交谈的“任何”方式。
-
对于不同的客户端,您将拥有不同的文件描述符,对吧...?
-
您的帖子主题具有误导性,因为它不是关于客户端的创建而是关于服务器如何区分它们。
-
另一个(正式误导)问题是
struct threadArguments中文件描述符的命名。您所称的listeningSocketDescriptor是不是 列表套接字,而是连接的(通过列表套接字serverSocketFD被accept()ed 连接)。调用connected socket和accepted socket可能也...,无论如何调用它connected socket更适合,因为它连接到由connect()返回的客户端套接字... ;-)
标签: c sockets networking network-programming pthreads