预备知识
因为UDP是无连接,不可靠,并且以数据报进行传输数据的方式,所以我们实现的时候只需要用到socket和bind即可
一.服务端
1.1 创建套接字
创建套接字很简单,只需要调用socket函数即可参数AF_INET是ipv4然后SOCK_DGRAM代表使用的UDP进行传输,创建完套接字后,需要进行判断套接字是否创建成功
int serfd=0;
serfd=socket(AF_INET,SOCK_DGRAM,0);
if(serfd<0)
{
perror("socke failed");
return -1;
}
printf("socket success\n");
1.2 绑定套接字ip地址和端口信息
因为我们使用的是ipv4 所以我们传入的结构为sockaddr_in类型,并把他的协议家族和ip和prot进行传入,然后调用bind函数进行绑定,绑定完成后记得判断是否绑定成功。
int ret=0;
struct sockaddr_in seraddr={0};
seraddr.sin_family=AF_INET;
seraddr.sin_addr.s_addr=inet_addr(argv[1]);
seraddr.sin_port=htons(atoi(argv[2]));
ret=bind(serfd,(struct sockaddr *)&seraddr,sizeof(seraddr));
if(ret<0)
{
perror("bind failed");
close(serfd);
return -1;
}
1.3 接收和发送信息
接收recvfrom和发送sendto用这俩个函数即可,可以看预备知识这俩个函数怎么使用,这里用的是死循环,一直可以接收发送进行数据传输。
while(1)
{
int addrlen=0;
char buf[1024]={0};
struct sockaddr_in clientaddr={0};
addrlen=sizeof(clientaddr);
ret = recvfrom(serfd,buf,sizeof(buf),0,(struct sockaddr *)&clientaddr,(socklen_t*)&addrlen);
if(ret<0)
{
perror("recvfrom failed");
close(serfd);
return -1;
}
printf("IP=%s,port=%u\n",inet_ntoa(clientaddr.sin_addr),ntohs(clientaddr.sin_port));
printf("recvfrom success\n");
printf("receive: %s\n",buf);
//向客户端发送消息
memset(buf,0,sizeof(buf));
scanf("%s",buf);
ret=sendto(serfd,buf,strlen(buf),0,(struct sockaddr *)&clientaddr,addrlen);
if(ret<0)
{
perror("sendto failed");
close(serfd);
return -1;
}
printf("sendto success\n");
}
close(serfd);
return 0;
}
二. 客户端
2.1 创建套接字
想要进行传输,首要就是创建套接字,
int clifd = 0;
clifd = socket(AF_INET, SOCK_DGRAM, 0);
if (clifd < 0)
{
perror("socke failed");
return -1;
}
printf("socket success\n");
2.2 发送和接受数据
客户端不用bind信息,知道服务端的ip和端口,直接进行传输信息即可,代码原理跟服务端相同,只不过客户端先进行发送数据
while (1)
{
int tolen = 0;
int ret = 0;
char buf[1024] = {0};
scanf("%s", buf);
struct sockaddr_in seraddr = {0};
seraddr.sin_family = AF_INET;
seraddr.sin_addr.s_addr = inet_addr(argv[1]);
seraddr.sin_port = htons(atoi(argv[2]));
tolen = sizeof(seraddr);
ret = sendto(clifd, buf, strlen(buf), 0, (struct sockaddr *)&seraddr, tolen);
if (ret < 0)
{
perror("sendto failed");
close(clifd);
return -1;
}
printf("sendto success\n");
// 接收发送自服务器的消息
ret = recvfrom(clifd, buf, sizeof(buf), 0, NULL, NULL);
if (ret < 0)
{
perror("recvfrom failed");
close(clifd);
return -1;
}
printf("recvfrom success\n");
printf("receive: %s\n", buf);
}
close(clifd);
三.整体代码
3.1 服务端
#include<stdio.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<string.h>
#include<unistd.h>
#include<netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
//创建UDP实现服务器和客户端的通信
int main(int argc, char *argv[])
{
if (argc != 3)
{
printf("Usage ./dict_server [ip] [port]\n");
return 1;
}
//创建socket连接
int serfd=0;
serfd=socket(AF_INET,SOCK_DGRAM,0);
if(serfd<0)
{
perror("socke failed");
return -1;
}
printf("socket success\n");
//绑定IP地址和端口信息
int ret=0;
struct sockaddr_in seraddr={0};
seraddr.sin_family=AF_INET;
seraddr.sin_addr.s_addr=inet_addr(argv[1]);
seraddr.sin_port=htons(atoi(argv[2]));
ret=bind(serfd,(struct sockaddr *)&seraddr,sizeof(seraddr));
if(ret<0)
{
perror("bind failed");
close(serfd);
return -1;
}
printf("bind success\n");
//接收发送自客户端的消息
while(1)
{
int addrlen=0;
char buf[1024]={0};
struct sockaddr_in clientaddr={0};
addrlen=sizeof(clientaddr);
ret = recvfrom(serfd,buf,sizeof(buf),0,(struct sockaddr *)&clientaddr,(socklen_t*)&addrlen);
if(ret<0)
{
perror("recvfrom failed");
close(serfd);
return -1;
}
printf("IP=%s,port=%u\n",inet_ntoa(clientaddr.sin_addr),ntohs(clientaddr.sin_port));
printf("recvfrom success\n");
printf("receive: %s\n",buf);
//向客户端发送消息
memset(buf,0,sizeof(buf));
scanf("%s",buf);
ret=sendto(serfd,buf,strlen(buf),0,(struct sockaddr *)&clientaddr,addrlen);
if(ret<0)
{
perror("sendto failed");
close(serfd);
return -1;
}
printf("sendto success\n");
}
close(serfd);
return 0;
}
3.2 客户端
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
// 创建UDP实现服务器和客户端的通信
// 创建socket连接
int main(int argc, char *argv[])
{
if (argc != 3)
{
printf("Usage ./dict_server [ip] [port]\n");
return 1;
}
// 创建socket连接
int clifd = 0;
clifd = socket(AF_INET, SOCK_DGRAM, 0);
if (clifd < 0)
{
perror("socke failed");
return -1;
}
printf("socket success\n");
// 向服务器发送消息
while (1)
{
int tolen = 0;
int ret = 0;
char buf[1024] = {0};
scanf("%s", buf);
struct sockaddr_in seraddr = {0};
seraddr.sin_family = AF_INET;
seraddr.sin_addr.s_addr = inet_addr(argv[1]);
seraddr.sin_port = htons(atoi(argv[2]));
tolen = sizeof(seraddr);
ret = sendto(clifd, buf, strlen(buf), 0, (struct sockaddr *)&seraddr, tolen);
if (ret < 0)
{
perror("sendto failed");
close(clifd);
return -1;
}
printf("sendto success\n");
// 接收发送自服务器的消息
ret = recvfrom(clifd, buf, sizeof(buf), 0, NULL, NULL);
if (ret < 0)
{
perror("recvfrom failed");
close(clifd);
return -1;
}
printf("recvfrom success\n");
printf("receive: %s\n", buf);
}
close(clifd);
return 0;
}