【发布时间】:2021-12-20 02:16:30
【问题描述】:
对于我的一门大学课程,我必须用 C 语言实现一个使用 UDP Client-Server 的简单聊天程序,这是老师发给我们的描述:
你应该开发一个私人聊天环境来交流 主机之间的短信。消息加密是可选的,但不是必需的。 该项目应由2个主要模块组成:
- 服务器:接收每条消息并将其存储在一种聊天数据库中。 一个非常幼稚的数据库将包含在
User结构中, 包含所有内容(登录凭据、聊天...)。 每个Chat结构都包含实际消息。- 客户端:提供了一个非常简单的界面来选择一个 接收我们的消息,然后编写消息的内容。 需要登录。如果接收者未订阅,则返回错误。
该项目应该至少有 3 个用户进行测试:)
我设法实现了身份验证阶段,但是在尝试实现消息交换阶段时我卡住了。当我尝试将在线用户的linked_list从服务器发送到客户端时,执行会冻结,不仅如此,它还会产生一些随机行为,有时会在第一次尝试时卡住,有时在第二次尝试时会卡住,依此类推。我还注意到,当我在客户端中引入一个单独的线程来处理收件箱中的消息时,情况变得比以前更频繁地卡住了。我将添加负责发送和接收在线用户的函数的代码以及指向我的 git repo 的链接,如果你愿意,你可以在其中找到完整的代码。
这是服务器中的代码:
void Send_list(ListHead* head, int sockfd,struct sockaddr_in cliaddr, int size){
int written_bytes;
int len = sizeof(cliaddr);
char username[50];
if(head->size == 1){
return;
}
ListItem* aux = head->first;
for(int i=0;i<size;i++){
memset(username,0,sizeof(username));
UserListItem* uitem = (UserListItem*) aux;
strcpy(username,uitem->user.username);
do{
written_bytes = 0;
written_bytes = sendto(sockfd,(const char *)username,strlen(username),0,(const struct sockaddr*)&cliaddr,len);
}while(written_bytes != strlen(username));
printf("\nusername mandato: %s",username);
printf("\n");
if(aux->next){
aux = aux->next;
}
}
}
这是客户端中的代码:
int recv_list(int sockfd,struct sockaddr_in servaddr, ListHead* head,int size, char username[50]){
char onuser[50];
int len = sizeof(servaddr);
int read_bytes;
int idx = 1;
if(size == 1){
return 1;
}
for(int i=0;i<size;i++){
read_bytes = recvfrom(sockfd,(char *)onuser,sizeof(onuser),0,(struct sockaddr*)&servaddr,&len );
onuser[read_bytes] = '\0';
if(List_find_by_username(head,onuser) == 0 || strcmp(onuser,username)){
UserListItem* uitem = malloc(sizeof(UserListItem));
memset(uitem,0,sizeof(UserListItem));
UList_init(uitem,onuser);
uitem->idx = idx++;
ListItem* result = List_insert(head,head->last,(ListItem*)uitem);
assert(result);
}
memset(onuser,0,sizeof(onuser));
}
UserList_print(head);
return 0;
}
这是我的 git 仓库的链接:https://gitlab.com/antonio_ciprani/so-progetto-20_21
我在基于 Ubuntu 的系统中工作。
我真的希望有人可以帮助我,因为这让我发疯:(
【问题讨论】:
-
sendto返回错误会发生什么(当它返回-1时)? -
我还建议您花时间学习如何调试您的程序。就像使用 debugger 来逐句执行代码,同时监控变量及其值。
-
@Someprogrammerdude 您是否暗示冻结是由于对 sendto 结果缺乏控制而发生的?我也尝试使用 Valgrind 和 gdb,但我无法理解问题到底发生在哪里,仅在这两个函数中
-
如果
sendto失败一次返回-1,会继续失败返回-1,导致死循环。这会让你的程序看起来像是“卡住了”。 -
@Someprogrammerdude 谢谢,我已经按照您的建议添加了一个 break 语句以防出现 -1 结果并且工作正常,直到我取消注释客户端中收件箱线程的代码并且尽快我已经完成了一切都停止了工作,我检查并添加了对 sendtos 和 recvfroms 的控制但似乎没有工作,你可能知道为什么会这样吗?
标签: c udp client-server