版权声明:私藏源代码是违反人性的罪恶行为!博客转载无需告知,学无止境。 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所示,不管客户机输入的报文是长或段,因为在服务器端的代码实现中,一次只会读取5个有效字符。那如果服务器端收到的字符多于5个怎么办?UDP是这样处理的:你可以没有时间处理,内核会为你保留;但是一旦进行读取,必须一次性将报文全部读取完,剩下的直接丢弃。