我试图使用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;
}
在这里,我遇到了细分错误。考虑了一下之后,我了解到“下一个”指针指向服务器程序地址空间中的一个地址,因此客户端可以访问它。因此,我使用了一个字符串数组来传递d_name列表,很显然,它可以正常工作。
所以,我的问题是:
1。有什么方法可以通过套接字连接传递链接列表吗?
2。如果不是,那么通过网络传递组成文件和目录列表的最佳方法是什么?在实际的NFS中如何实现?
答案 0 :(得分:2)
- 是否可以通过套接字连接传递链表?
不直接,不。相反,您需要做的是通过套接字连接以某种定义明确的格式发送一些字节,接收程序可以使用这些字节来构造相同的链接列表。
正如其他人在评论中指出的那样,通过套接字连接发送指针是没有用的,因为指针仅在发送进程的内存空间内有效-即使您确实跨过发送了指针的值,也不会不能成为接收者存储空间中的有效指针。
幸运的是,无需发送指针。相反,只需发送有效载荷数据(在您的情况下为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)