通过套接字传递链表
Passing a linked list over a socket
我试图使用 tcp 套接字实现一种非常简单的 NFS 形式。除了 "ls" 命令外,所有功能都正常工作。我的计划是使用链表结构来传递当前目录中的组成文件和目录名称的列表。我写了下面的代码:
struct lnode
{
char name[256];
struct lnode* next;
};
DIR* drptr = opendir("."); //as of now, only current directory is considered
if(drptr==NULL)
{
perror("Could not open");
}
else
{
struct dirent* drnt;
struct lnode* head = NULL,*tail = NULL;
drnt = readdir(drptr);
while(drnt!=NULL)
{
if(strcmp(drnt->d_name,".")!=0&&strcmp(drnt->d_name,"..")!=0)
{
if(head==NULL)
{
head = (struct lnode*)malloc(sizeof(struct lnode));
strcpy(head->name,drnt->d_name);
head->next = NULL;
teail = head;
}
else
{
tail->next = (struct lnode*)malloc(sizeof(struct lnode));
strcpy(tail->next->name,drnt->d_name);
tail->next->next = NULL;
tail = tail->next;
}
}
else
{
break;
}
drnt = readdir(drptr);
}
write(1,head,sizeof(lnode)); // the socket is duped to 1, so 1 is used for socket communication
}
在客户端,我是这样阅读的:
struct lnode* l,*q;
recv(sfd,l,sizeof(struct lnode),0);
q = l;
while(q!=NULL)
{
printf("%s\n",q->name);
q = q->next;
}
在这里,我遇到了分段错误。想了想,我明白 'next' 指针指向服务器程序地址 space 中的一个地址,因此客户端可以访问它。所以我使用了一个字符串数组来传递 d_name 列表,很明显,它工作得很好。
那么,我的问题是:
1.有什么方法可以通过套接字连接传递链表吗?
2。如果不是,那么通过网络传递组成文件和目录列表的最佳方法是什么?在真正的NFS中是如何实现的?
- Is there any way of passing a linked list over a socket connection?
不直接,不。您需要做的是通过套接字连接发送一些字节,以某种定义明确的格式,接收程序可以使用该格式来构造相同的链表。
正如其他人在评论中指出的那样,通过套接字连接发送指针是没有用的,因为指针仅在发送进程的内存中有效 space——即使您确实发送了指针的值,它不会是接收器内存中的有效指针 space.
幸好不用指点;相反,只需发送有效载荷数据(在您的情况下,name
数组)并让接收方创建一个新的链表,其中包含接收到的有效载荷数据。
例如(伪代码,注意有很多方法可以做到这一点,这只是一种对我来说相当简单的方法):
// compute the length of the linked list we want to send
int numNodesInLinkedList = 0;
struct lnode * n = headNode;
while(n)
{
numNodesInLinkedList++;
n = n->next;
}
// sender: First, send a string telling the receiver how many nodes to expect
char headerBuffer[256];
sprintf(headerBuffer, "%i", numNodesInLinkedList);
send(sfd, headerBuffer, sizeof(headerBuffer), 0);
// Then send that many node's worth of name-data
struct lnode * n = headNode;
while(n)
{
send(sfd, n->name, sizeof(n->name), 0);
n = n->next;
}
... 然后接收方将 运行 编码如下(同样,伪代码;真实代码将进行适当的错误检查等):
// receiver: First, receive the string containing the number-of-nodes-to-receive
char headerBuffer[256];
recv(sfd, headerBuffer, sizeof(headerBuffer), MSG_WAITALL);
const int numNodesInLinkedList = atoi(headerBuffer);
struct lnode * headNode = NULL;
struct lnode * tailNode = NULL;
// Then receive that many names, and place them into our new linked-list
for (int i=0; i<numNodesInLinkedList; i++)
{
struct lnode * newNode = malloc(sizeof(struct lnode));
newNode->next = NULL;
recv(sfd, newNode->name, sizeof(newNode->name), MSG_WAITALL);
if (tailNode)
{
tailNode->next = newNode;
tailNode = newNode;
}
else tailNode = headNode = newNode;
}
// at this point, headNode points to the start of the received linked-list
// and tailNode points to the last received node in the list
// (or both headNode and tailNode are NULL if the list was empty)
我试图使用 tcp 套接字实现一种非常简单的 NFS 形式。除了 "ls" 命令外,所有功能都正常工作。我的计划是使用链表结构来传递当前目录中的组成文件和目录名称的列表。我写了下面的代码:
struct lnode
{
char name[256];
struct lnode* next;
};
DIR* drptr = opendir("."); //as of now, only current directory is considered
if(drptr==NULL)
{
perror("Could not open");
}
else
{
struct dirent* drnt;
struct lnode* head = NULL,*tail = NULL;
drnt = readdir(drptr);
while(drnt!=NULL)
{
if(strcmp(drnt->d_name,".")!=0&&strcmp(drnt->d_name,"..")!=0)
{
if(head==NULL)
{
head = (struct lnode*)malloc(sizeof(struct lnode));
strcpy(head->name,drnt->d_name);
head->next = NULL;
teail = head;
}
else
{
tail->next = (struct lnode*)malloc(sizeof(struct lnode));
strcpy(tail->next->name,drnt->d_name);
tail->next->next = NULL;
tail = tail->next;
}
}
else
{
break;
}
drnt = readdir(drptr);
}
write(1,head,sizeof(lnode)); // the socket is duped to 1, so 1 is used for socket communication
}
在客户端,我是这样阅读的:
struct lnode* l,*q;
recv(sfd,l,sizeof(struct lnode),0);
q = l;
while(q!=NULL)
{
printf("%s\n",q->name);
q = q->next;
}
在这里,我遇到了分段错误。想了想,我明白 'next' 指针指向服务器程序地址 space 中的一个地址,因此客户端可以访问它。所以我使用了一个字符串数组来传递 d_name 列表,很明显,它工作得很好。
那么,我的问题是:
1.有什么方法可以通过套接字连接传递链表吗?
2。如果不是,那么通过网络传递组成文件和目录列表的最佳方法是什么?在真正的NFS中是如何实现的?
- Is there any way of passing a linked list over a socket connection?
不直接,不。您需要做的是通过套接字连接发送一些字节,以某种定义明确的格式,接收程序可以使用该格式来构造相同的链表。
正如其他人在评论中指出的那样,通过套接字连接发送指针是没有用的,因为指针仅在发送进程的内存中有效 space——即使您确实发送了指针的值,它不会是接收器内存中的有效指针 space.
幸好不用指点;相反,只需发送有效载荷数据(在您的情况下,name
数组)并让接收方创建一个新的链表,其中包含接收到的有效载荷数据。
例如(伪代码,注意有很多方法可以做到这一点,这只是一种对我来说相当简单的方法):
// compute the length of the linked list we want to send
int numNodesInLinkedList = 0;
struct lnode * n = headNode;
while(n)
{
numNodesInLinkedList++;
n = n->next;
}
// sender: First, send a string telling the receiver how many nodes to expect
char headerBuffer[256];
sprintf(headerBuffer, "%i", numNodesInLinkedList);
send(sfd, headerBuffer, sizeof(headerBuffer), 0);
// Then send that many node's worth of name-data
struct lnode * n = headNode;
while(n)
{
send(sfd, n->name, sizeof(n->name), 0);
n = n->next;
}
... 然后接收方将 运行 编码如下(同样,伪代码;真实代码将进行适当的错误检查等):
// receiver: First, receive the string containing the number-of-nodes-to-receive
char headerBuffer[256];
recv(sfd, headerBuffer, sizeof(headerBuffer), MSG_WAITALL);
const int numNodesInLinkedList = atoi(headerBuffer);
struct lnode * headNode = NULL;
struct lnode * tailNode = NULL;
// Then receive that many names, and place them into our new linked-list
for (int i=0; i<numNodesInLinkedList; i++)
{
struct lnode * newNode = malloc(sizeof(struct lnode));
newNode->next = NULL;
recv(sfd, newNode->name, sizeof(newNode->name), MSG_WAITALL);
if (tailNode)
{
tailNode->next = newNode;
tailNode = newNode;
}
else tailNode = headNode = newNode;
}
// at this point, headNode points to the start of the received linked-list
// and tailNode points to the last received node in the list
// (or both headNode and tailNode are NULL if the list was empty)