先记录下关于UDP的基础知识点
UDP的基础知识点
包括的头文件和常用的函数
#include <sys/types.h>
#include <sys/socket.h>
1.socket函数原型
int socket(int domain, int type, int protocol);
功能:
创建一个socket
参数说明:
参数1:设置网络通信的域 这里的AF_INET 表示IPV4的网络类型;使用AF_INET6的网络类型
参数2:socket的数据类型 这里的SOCK_DGRAM表示UDP类型;使用SOCK_STREAM表示TCP类型
参数3:协议类型 一般置为0
例子:
int sockfd = socket(AF_INET,SOCK_DGRAM,0);
2.sendto函数原型
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen);
功能:
sendto发送指令给指定的服务器
参数说明:
参数1:监听端口的套接字文件描述符 通过socket返回
参数2:发送缓冲区
参数3:缓冲区的大小
参数4:一般置为0
参数5:sockaddr结构体地址 这个结构体包含 IP地址 端口号 网络通信域
参数6:参数5的长度 可以用sizeof(sockaddr_in)获取
例子:
int sendlength = sendto(sockfd,buffer,strlen(buffer),0, (struct sockaddr*)addr, len);
3.recvfrom函数原型
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen);
功能:
接收服务端返回的信息
参数说明:
第一个参数sockfd:正在监听端口的套接口文件描述符,通过socket获得
第二个参数buf:接收缓冲区,往往是使用者定义的数组,该数组装有接收到的数据
第三个参数len:接收缓冲区的大小,单位是字节
第四个参数flags:填0即可
第五个参数src_addr:指向发送数据的主机地址信息的结构体,也就是我们可以从该参数获取到数据是谁发出的
第六个参数addrlen:表示第五个参数所指向内容的长度
返回值:成功:返回接收成功的数据长度 失败 返回-1
进行UDP通信的时候 端口是一定要一致的 否则无法收到消息
//Step2 给sockaddr_in结构体赋值(IP地址 端口号 网络通信域)
bzero(&addr,sizeof(struct sockaddr_in));
addr.sin_family=AF_INET;
addr.sin_port=htons(SERVER_PORT);
//addr.sin_addr.s_addr = htonl("139.224.117.109");
//inet_aton("139.224.117.109", &addr.sin_addr);
if(inet_aton("127.0.0.1",&addr.sin_addr)<0)
例子:
struct sockaddr_in addr;
bzero(&addr,sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_port = htons(SERVER_PORT);
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
UDP的server例子:
/*
2019-11-30 11:24:14
一个简单的UDP server的实现
*/
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <arpa/inet.h>
#define SERVER_PORT 9989
#define MAX_MSG_SIZE 1024
int main()
{
int sockfd;
int addrlen,n;
char msg[MAX_MSG_SIZE];
struct sockaddr_in addr;
//Step1 创建socket
sockfd=socket(AF_INET,SOCK_DGRAM,0);
if(sockfd<0)
{
fprintf(stderr,"Socket Error:%s\n",strerror(errno));
exit(1);
}
//Step2 给sockaddr_in结构体赋值
bzero(&addr,sizeof(struct sockaddr_in));
addr.sin_family=AF_INET;
addr.sin_addr.s_addr=htonl(INADDR_ANY);
addr.sin_port=htons(SERVER_PORT);
//Step3 绑定sock
if(bind(sockfd,(struct sockaddr *)&addr,sizeof(struct sockaddr_in))<0)
{
fprintf(stderr,"Bind Error:%s\n",strerror(errno));
exit(1);
}
while(1)
{
bzero(msg,sizeof(msg));
//Step4 开始接收消息(来自客户端的消息)
n=recvfrom(sockfd,msg,MAX_MSG_SIZE,0,(struct sockaddr*)&addr,&sizeof(struct sockaddr_in));
if (n <= 0)
break;
fprintf(stdout,"Server have received: %s\n",msg);
//这里做一个正常退出的条件
if (strcmp(msg,"exit\n") == 0)
{
printf("Exit server\n");
break;
}
}
//Step5 当接收到的值异常的时候 结束这个流程 释放socket
close(sockfd);
}
UDP client的例子
/*
2019-11-30 11:32:19
一个简单的UDP的client
*/
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#define SERVER_PORT 9999
#define MAX_BUF_SIZE 1024
int main()
{
char buffer[MAX_BUF_SIZE];
int sockfd,n;
struct sockaddr_in addr;
//Step1 创建socket
sockfd=socket(AF_INET,SOCK_DGRAM,0);
if(sockfd<0)
{
fprintf(stderr,"Socket Error:%s\n",strerror(errno));
exit(1);
}
//Step2 对sockaddr_in进行赋值
bzero(&addr,sizeof(struct sockaddr_in));
addr.sin_family=AF_INET;
addr.sin_port=htons(SERVER_PORT);
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
while(1)
{
bzero(buffer,MAX_BUF_SIZE);
printf("Please input char:\n");
fgets(buffer,MAX_BUF_SIZE,stdin);
//Step3 发送消息到服务端
sendto(sockfd,buffer,strlen(buffer),0, (struct sockaddr *)&addr, sizeof(struct sockaddr_in));
//这里做一个退出的条件 输入exit的时候退出
if (strcmp(buffer,"exit\n") == 0)
break;
}
//Step4 结束消息
close(sockfd);
}
编译就使用gcc来进行编译就好了
gcc -o client client.c
gcc -o server server.c
运行结果:
这里记录一个问题(一个警告)
example_tcp_client.c:53:5: warning: implicit declaration of function ‘write’ [-Wimplicit-function-declaration]
write(sockfd,buffer,strlen(buffer));
^
example_tcp_client.c:56:5: warning: implicit declaration of function ‘close’ [-Wimplicit-function-declaration]
close(sockfd);
这个严格上说不算错误 只是警告,这里加上头文件 #include <unistd.h> 即可解决此问题