计算机网络_验证UDP特性(一次未将报文数据读完,剩余部分将被丢弃)

版权声明:私藏源代码是违反人性的罪恶行为!博客转载无需告知,学无止境。 https://blog.csdn.net/qq_41822235/article/details/83965631

一、 思路

服务器端和客户端进行报文交互,客户端每次向服务器端发送消息,服务器端只读取5个有效字符,观察情况:

二、 代码实现

#include<netinet/in.h> //struct sockaddr; struct sockaddr_in;
#include<sys/socket.h> //socket() bind() recvfrom() sendto()
#include<arpa/inet.h> //字节序 htons() 返回以网络字节序表示的16位无符号
#include<string.h> //memset()
#include<assert.h> //assert()
#include<stdio.h> //printf()

2.1 服务器端

#include<netinet/in.h> //struct sockaddr; struct sockaddr_in;
#include<sys/socket.h> //socket() bind() recvfrom() sendto()
#include<arpa/inet.h> //字节序 htons() 返回以网络字节序表示的16位无符号
#include<string.h> //memset()
#include<assert.h> //assert()
#include<stdio.h> //printf()

int main()
{
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);//地址族 套接字类型 协议
    assert(-1 != sockfd);

    struct sockaddr_in ser, cli;
    memset(&ser, 0, sizeof(ser)); //格式化服务器端
  
    //设置服务器端套接字
    ser.sin_family = AF_INET; //ipV4
    ser.sin_port = htons(6500);	//端口号为6000 主机序-> 网络序 
    ser.sin_addr.s_addr = inet_addr("127.0.0.1");//ip地址

    //将套接字和地址结构进行绑定
    int res = bind(sockfd, (struct sockaddr*)&ser, sizeof(ser));
    assert(-1 != res);

    while(1)
    {
	    char recvbuf[6] = {'\0'}; //接受5个有效字符 保留一个结束符
	    int len = sizeof(cli); 
	
	    //套接字缓冲区的大小可能会改变
	    int n = recvfrom(sockfd, recvbuf, 5, 0, (struct sockaddr*)&cli, &len);
	
	    if(n <= 0) //本次失败继续进行下一次客户机和服务器端通信
	    {
	        printf("recvfrom error!\n");
	        continue;
	    }

	    printf("%s\n", recvbuf); //打印输出从客户端接收的数据
    }
    close(sockfd); //关闭服务器端套接字
}

2.2 客户端

#include<string.h>  //memset()
#include<arpa/inet.h>	//字节序处理 htons()
#include<sys/socket.h>	//sendto() recvfrom() socket()
#include<netinet/in.h>	//struct sockaddr; struct sockaddr_in;
#include<assert.h>  //assert()
#include<stdio.h>   //printf()
#include<stdlib.h>  //exit()

//main主函数传参 argc反映数组argv元素的个数
int main(int argc, char* argv[])
{
    if(argc < 3)
    {
	    printf("please choose server's IP && port\n");
	    exit(0);
    }
    
    //从命令行读入端口号
    int port;
    sscanf(argv[2], "%d", &port);
    
    //地址族 套机字类型 所使用的协议 值位0表明和套接字类型自动匹配的协议
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0); 
    assert(-1 != sockfd);

    struct sockaddr_in ser, cli;
    memset(&ser, 0, sizeof(ser));
    
    //配置服务器端地址
    ser.sin_family = AF_INET;
    ser.sin_addr.s_addr = inet_addr(argv[1]);
    ser.sin_port = htons(port);

    while(1)
    {
	    //打印输出提示语句
	    printf("please input:");
	    fflush(stdout);

	    char buf[128] = {'\0'}; 
	    fgets(buf, 127, stdin); //留下1位用作结束符
	    buf[strlen(buf) - 1] = '\0';

	    if(0 == strncmp(buf, "end", 3)) //客户端命令行输入end
	    {
	        close(sockfd);
	        break;
	    }

	    sendto(sockfd, buf, strlen(buf), 0,(struct sockaddr*)&ser, sizeof(ser));
    }
    close(sockfd); //关闭文件描述符
}

2.3 运行结果

图1 验证结果

如图 1所示,不管客户机输入的报文是长或段,因为在服务器端的代码实现中,一次只会读取5个有效字符。那如果服务器端收到的字符多于5个怎么办?UDP是这样处理的:你可以没有时间处理,内核会为你保留;但是一旦进行读取,必须一次性将报文全部读取完,剩下的直接丢弃。 

猜你喜欢

转载自blog.csdn.net/qq_41822235/article/details/83965631