使用C&;实现停止和等待;UDP,以及是什么导致';资源暂时不可用';?
我正在用c和udp套接字编程实现停止&等待。为了模拟这个协议,我编写了两个代码 这是我的使用C&;实现停止和等待;UDP,以及是什么导致';资源暂时不可用';?,c,sockets,udp,recvfrom,C,Sockets,Udp,Recvfrom,我正在用c和udp套接字编程实现停止&等待。为了模拟这个协议,我编写了两个代码 这是我的server.c文件: #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/socket.h> #inclu
server.c
文件:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <unistd.h>
#include <arpa/inet.h>
typedef struct packet{
char data[1024];
}Packet;
typedef struct frame{
int frame_kind; //ACK:0, SEQ:1 FIN:2
int sq_no;
int ack;
Packet packet;
}Frame;
int main(int argc, char** argv)
{
int sockfd;
int clilen;
int state;
int n;
int sum;
int recv_result;
int frame_id = 0;
Packet packet;
Frame frame;
Frame recv_frame;
char buffer[1024] = "";
struct timeval tv;
struct sockaddr_in serveraddr, clientaddr;
FILE* infile = fopen(argv[2], "r");
if(argc != 3)
{
perror("error! usage: $./server <PORT> filename\n");
exit(1);
}
if(infile == NULL)
{
printf("error! failed to open the file.\n");
exit(0);
}
clilen = sizeof(clientaddr);
sockfd = socket(AF_INET, SOCK_DGRAM, 0); //using diagram instead of stream-- UDP
if(sockfd < 0)
{
perror("socket error: ");
exit(0);
}
bzero(&serveraddr, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
serveraddr.sin_port = htons(atoi(argv[1])); //set port number 9999
//set socket option -- timeout is 100000 microseconds
tv.tv_sec = 1;
tv.tv_usec = 0;
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (char*)&tv, sizeof(struct timeval));
state = bind(sockfd, (struct sockaddr*)&serveraddr, sizeof(serveraddr));
if(state == -1)
{
perror("bind error: ");
exit(0);
}
do{
n = fscanf(infile, "%s", buffer);
strcpy(packet.data, buffer);
memcpy(&(frame.packet), &packet, sizeof(Packet));
frame.frame_kind = 1; //SEQ
frame.sq_no = frame_id;
frame.ack = 0;
printf("flag2");
while(1)
{
sendto(sockfd, &frame, sizeof(frame), 0, (struct sockaddr*)&clientaddr, (socklen_t)clilen);
printf("Frame %d sent\n", frame_id);
recv_result = recvfrom(sockfd, &recv_frame, sizeof(recv_frame), 0,(struct sockaddr*)&clientaddr, &clilen );
if(recv_result > 0 && recv_frame.sq_no == 0 && recv_frame.ack == frame_id){
printf("Ack %d received\n", recv_frame.sq_no);
break;
}else{
printf("Frame %d time expired\n", frame_id);
}
}
frame_id++;
}while(n > 0);
printf("finished\n");
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
typedef struct packet{
char data[1024];
}Packet;
typedef struct frame{
int frame_kind; //ACK:0, SEQ:1 FIN:2
int sq_no;
int ack;
Packet packet;
}Frame;
int main(int argc, char *argv[])
{
int sock;
int str_len;
socklen_t adr_sz;
FILE* outfile = fopen("output.txt", "w");
struct sockaddr_in serv_adr, from_adr;
Frame ackframe, recv_frame;
int frame_id;
int recv_result;
struct timeval tv;
if(argc!=3){
printf("Usage : %s <IP> <port>\n", argv[0]);
exit(1);
}
sock=socket(PF_INET, SOCK_DGRAM, 0);
if(sock==-1)
{
printf("error! failed to open the socket\n");
exit(1);
}
memset(&serv_adr, 0, sizeof(serv_adr));
adr_sz = sizeof(serv_adr);
serv_adr.sin_family=AF_INET;
serv_adr.sin_addr.s_addr=inet_addr(argv[1]);
serv_adr.sin_port=htons(atoi(argv[2]));
tv.tv_sec = 1;
tv.tv_usec = 0;
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char*)&tv, sizeof(struct timeval));
frame_id = 0;
while(1)
{
recv_result = recvfrom(sock, &recv_frame, sizeof(recv_frame), 0,(struct sockaddr*)&serv_adr, &adr_sz);
perror("error: ");
printf("data %s\n", recv_frame.packet.data);
printf("recv result %d\n", recv_result);
printf("recv frame=%d, frame_kind = %d\n", recv_frame.sq_no, recv_frame.frame_kind);
if(recv_result > 0 && recv_frame.frame_kind == 1 && recv_frame.sq_no==frame_id){
printf("Frame %d received\n", recv_frame.sq_no);
fprintf(outfile, "%s", recv_frame.packet.data);
ackframe.frame_kind = 0;
ackframe.ack = recv_frame.sq_no + 1;
printf("Ack %d sent\n", ackframe.ack);
sendto(sock, &recv_frame, sizeof(recv_frame), 0,(struct sockaddr*)&serv_adr, adr_sz);
break;
}else{
printf("Frame %d time expired\n", frame_id);
}
}
close(sock);
fclose(outfile);
return 0;
}
服务器需要3个参数:/server
客户端还需要3个参数:/client
它被执行,但客户端的recvfrom
始终返回-1
我读了一些主题相同的问题,但无法从代码中找出错误。有没有办法用recvfrom
和sendto
修复我的代码?或者我需要使用select
功能吗?(我将只与一台服务器和一台客户端通信。)该“客户端”和“服务器”程序包含一些可疑代码。首先让我们看一看“服务器”,它使用您尚未初始化的clientaddr
调用sendto
。谁知道你想把包送到哪里。事实上,这会导致未定义的行为,因为结构的内容是不确定的
然后让我们以客户机为例,在该客户机中,您在未绑定本地的套接字上调用recvfrom
。传递给recvfrom
的地址结构指针由recvfrom
函数填充,但其中的数据不以任何其他方式使用
可能还有其他问题,但这两个问题很突出。您确实意识到,
fread()
不会以null终止它所读取的内容吗?哦,我在最新的代码中修复了它,但没有修复其中一个代码。但我不认为这是“资源暂时不可用”错误的原因。考虑到您strcpy()
一些可能不是以null结尾的内容,然后您memcpy()
相同的内容,我不想为您调试此代码。如果像return-1
这样的系统调用,那么您可以(并且应该)调试此代码看看哪里出了问题。另外,errno
的值是未定义的,如果上一个函数没有实际失败,请不要选中errno
,除非上一个函数实际失败。您会收到该错误,因为您可能已将超时设置为低超时。如果没有要接收的内容,则recvfrom
函数将超时并返回该错误。至于为什么什么都没有收到是一个完全不同的故事,可能有100个不同的原因,但在快速浏览您的代码后,您的程序似乎有点不正常,我将在回答中解释更多。我修复了它。原因是……)