C UDP服务器没有响应客户端

C UDP服务器没有响应客户端,c,udp,C,Udp,正在开发一个旨在模拟网络中的数据层的程序。我已经正确地将消息发送到服务器,但是,客户端没有从服务器接收到ACK帧。这导致我的程序无休止地等待。如能帮助解决此事,我们将不胜感激 寄件人 #include <stdio.h> #include <unistd.h> #define MAXFRAME 97 main(int argc, char* argv[]){ char *frame; int len = 0; int c; dlinits

正在开发一个旨在模拟网络中的数据层的程序。我已经正确地将消息发送到服务器,但是,客户端没有从服务器接收到ACK帧。这导致我的程序无休止地等待。如能帮助解决此事,我们将不胜感激

寄件人

#include <stdio.h>
#include <unistd.h>
#define MAXFRAME  97
main(int argc, char* argv[]){
    char *frame;
    int len = 0;
    int c;
    dlinits("spirit.cba.csuohio.edu", 43525);
    frame = malloc(MAXFRAME);

    FILE *file = fopen(argv[1], "r");
    if (file == NULL)
        return NULL;

    while ((c = fgetc(file)) != EOF)
    {
        if(len == (MAXFRAME-1)){
            dlsend(frame, len, 0);
            len = 0;
            memset(frame,0,strlen(frame));
        }       

        frame[len++] = (char) c;
    }

    dlsend(frame, len, 1);




}
#包括
#包括
#定义MAXFRAME 97
main(int argc,char*argv[]){
字符*帧;
int len=0;
INTC;
dlinits(“spirit.cba.csuohio.edu”,43525);
帧=malloc(MAXFRAME);
FILE*FILE=fopen(argv[1],“r”);
if(file==NULL)
返回NULL;
而((c=fgetc(文件))!=EOF)
{
如果(len==(MAXFRAME-1)){
dlsend(帧,len,0);
len=0;
memset(帧,0,strlen(帧));
}       
帧[len++]=(char)c;
}
dlsend(帧,len,1);
}
接受者

#include <string.h>
#include <unistd.h>
char* dlrecv();

main(){
    char* test[100];
    dlinitr(43525);
    while(1){
        strcpy(test,dlrecv());

        printf("%s\n", test);
    }


}
#包括
#包括
char*dlrecv();
main(){
字符*测试[100];
dlinitr(43525);
而(1){
strcpy(test,dlrecv());
printf(“%s\n”,测试);
}
}
数据层

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#define BUFMAX 100

static int sk;
static struct sockaddr_in remote;
static struct sockaddr_in local;
static int fnum = 0;
static expFra = 0x00;

dlinits(char* host, int port){//initialize sender

    struct hostent *hp;
    sk = socket(AF_INET, SOCK_DGRAM, 0);

    remote.sin_family = AF_INET;

    hp = gethostbyname(host);
    if (hp == NULL){
        printf("Can't find host name\n");
        exit(1);
    }

    bcopy(hp->h_addr,&remote.sin_addr.s_addr,hp->h_length);

    remote.sin_port = ntohs(port);
}

dlinitr(int port){//initialize receiver
    int rlen = sizeof(remote);
    int len = sizeof(local);
    char buf[BUFMAX];

    sk = socket(AF_INET,SOCK_DGRAM,0);

    local.sin_family = AF_INET;
    local.sin_addr.s_addr = INADDR_ANY;
    local.sin_port = htons(port);
    bind (sk, &local,sizeof(local));

    getsockname(sk,&local,&len);

}

dlsend(char* msg, int len, int end){//send data
    int header = 0x00;
    int result;
    char *ackframe = malloc(3);
    unsigned char *nmsg;
    nmsg = malloc(100);
    if ((fnum%2) == 1){
        header = header|0x02;
    }
    if (end == 1){
        header = header|0x40;
    }
    header = header^0xff;
    printf("%x\n %x\n", header, 0);
    nmsg[0] = (char)header;
    len++;
    printf("%s\n", nmsg);
    memcpy(nmsg + 1, msg, strlen(msg));
    result = crc(nmsg, len);
    nmsg[len++] = ((result >> 8) & 0xff);
    nmsg[len++] = (result & 0xff);


    printf("%s\n", nmsg);
    sendto(sk,nmsg,len,0,&remote,sizeof(remote));

    read(sk,ackframe,3);
    printf("Ack Received: %s\n", ackframe);

    fnum++;
} 

char* dlrecv(){//receive data
    int result;
    int header;
    int ACK = 1;
    char alen = 1;
    char *ackframe = malloc(3);
    unsigned char* msg = malloc(100);
    while (ACK){
        recvfrom(sk,msg,BUFMAX,0,&remote,sizeof(remote));
        int len = strlen(msg);
        result = crc(msg, len);
        if (result == 0){
            msg[--len] = 0;
            msg[--len] = 0;
            header = msg[0];
            printf("Header %x expFra %x\n", header, expFra);
            header = header^0xff;
            printf("Header %x expFra %x\n", header, expFra);
            if ((header<<4) == (expFra<<4)){
                expFra = expFra^0x02;
                ackframe[0] = (0x10|header);
                result = crc(ackframe, alen);
                ackframe[alen++] = ((result >> 8) & 0xff);
                ackframe[alen++] = (result & 0xff);
                sendto(sk,ackframe,strlen(ackframe),0,&remote,sizeof(remote));
                printf("Ack Sent: %s\n", ackframe);
                ACK = 0;

            }
        }
    }
    printf("%s\n", msg);
    return ++msg;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#定义BUFMAX 100
静态int-sk;
远程中的静态结构sockaddr_;
本地的静态结构sockaddr_;
静态int fnum=0;
静态expFra=0x00;
dlinits(char*主机,int端口){//初始化发送方
结构主机*hp;
sk=插座(AF_INET,SOCK_DGRAM,0);
remote.sin_family=AF_INET;
hp=gethostbyname(主机);
如果(hp==NULL){
printf(“找不到主机名\n”);
出口(1);
}
b复制(hp->h\u addr和remote.sin\u addr.s\u addr,hp->h\u length);
remote.sin_port=ntohs(端口);
}
dlinitr(int端口){//初始化接收器
int rlen=sizeof(远程);
int len=sizeof(本地);
char buf[BUFMAX];
sk=插座(AF_INET,SOCK_DGRAM,0);
local.sin_family=AF_INET;
local.sin\u addr.s\u addr=INADDR\u ANY;
local.sin_port=htons(port);
绑定(sk和local,sizeof(local));
getsockname(sk、本地和len);
}
dlsend(char*msg,int len,int end){//send data
int头=0x00;
int结果;
char*ackframe=malloc(3);
无符号字符*nmsg;
nmsg=malloc(100);
如果((fnum%2)==1){
收割台=收割台| 0x02;
}
如果(结束==1){
收割台=收割台| 0x40;
}
页眉=页眉^0xff;
printf(“%x\n%x\n”,头,0);
nmsg[0]=(char)头;
len++;
printf(“%s\n”,nmsg);
memcpy(nmsg+1,msg,strlen(msg));
结果=crc(nmsg,len);
nmsg[len++]=(结果>>8)和0xff;
nmsg[len++]=(结果&0xff);
printf(“%s\n”,nmsg);
发送到(sk、nmsg、len、0和remote、sizeof(remote));
读取(sk,ackframe,3);
printf(“收到的确认:%s\n”,确认帧);
fnum++;
} 
char*dlrecv(){//接收数据
int结果;
int头;
int ACK=1;
char-alen=1;
char*ackframe=malloc(3);
无符号字符*msg=malloc(100);
while(ACK){
recvfrom(sk、msg、BUFMAX、0和remote、sizeof(remote));
int len=strlen(msg);
结果=crc(msg,len);
如果(结果==0){
msg[--len]=0;
msg[--len]=0;
header=msg[0];
printf(“头%x expFra%x\n”,头,expFra);
页眉=页眉^0xff;
printf(“头%x expFra%x\n”,头,expFra);

如果((header我对UDP的经验是,
read()
(您在
dlsend()
末尾使用的)是非常偶然的,特别是当与
sendto()
配对时。除非有充分的理由不这样做,否则将
read()
更改为
recvfrom()
应该可以解决问题

你的代码也会对不匹配的类型抛出很多警告。它们有点无害,但会使跟踪其他类型变得更加复杂

在这之后,最后的确认-
sendto()
使用了错误的套接字数据。拨弄一下,原因是您在(
sizeof(remote)
)中传递了一个整数,作为上一次
recvfrom()
调用中地址大小的指针。如果给定的初始大小太小,
recvfrom()
产生不可靠的结果。如果它需要的空间小于此值,它将更改该值以告诉您它使用了什么

因此,您需要在
结构中声明一个初始化为
sockaddr\u大小的整数,并将指向该整数的指针作为最后一个参数传递给它,您将获得地址的正确值,并能够发送确认


学到的重要经验应该是:(a)确保所有类型都正确,并检查每个警告;(b)检查每个套接字调用的返回值,如果返回
-1
,则打印错误。

您能谈谈您是如何运行这些程序的吗?它们是否在同一台机器(本地主机)上运行还是涉及多台机器?UDP传输不受保证,大多数防火墙都会丢弃此类流量等。因此,关于您的网络拓扑的一些信息是有保证的。每次我看到strlen()在网络代码中,我变得非常紧张…我做了建议的更改,但结果是一样的。在第一条消息之后,我仍然挂起,因为发件人没有收到任何消息。啊…我还没有找到它,但是
remote
在某个地方被破坏了。您会收到一个
无效参数
错误,如果您选中k
sin_family
sin_port
,它们被归零了。我明白了。我正在寻找,但我似乎找不到发生这种情况的原因。我想我设法把它全部运行了下来。我会发布代码,但为了调试的目的,我做了很多更改,它与您原来的过程并不太相似。如果您需要更多的c,请随时询问我真的很感谢你的帮助,是的,再澄清一下就好了