一、服务端
1.创建套接字
使用的函数是socket函数,即告诉编译器,你的服务器的通信方式、通信协议。我们的通信方式就选择网络通信AF_INET,通信协议选择UDP。
//1. 创建服务端套接字
int server = socket(AF_INET, SOCK_DGRAM, 0);
if(server < 0)
{
std::cerr << "socket create error." << std::endl;
return 1;
}
使用 man socket 查看函数使用方法
2.绑定IP和端口号
注:创建套接字的时候,既然选择的通信方式是AF_INET,用于存放服务端地址的数据类型那就是struct sockaddr_in。但是在填入bind函数的时候,bind函数使用的是统一接口,所以需要强转成struct sockaddr* 类型。
//2. 绑定IP端口号
//a.填充地址信息
struct sockaddr_in local;
local.sin_family = AF_INET; //选择协议家族(通信方式)AF_INET
uint16_t port = 8080;
local.sin_port = htons(port); //绑定端口,因为port是16位int型变量,是主机序列,需要转化为网络字节序
local.sin_addr.s_addr = INADDR_ANY; //如果是接收绑定指定ip的数据,那就是inet_addr("你的ip")
//如果不指定,那就是INADDR_ANY,表明凡是发送到8080端口的数据,你都选择接收,不管是服务器上哪个ip地址收到的
//b.使用bind函数绑定
int ret = bind(server,(struct sockaddr*)&local,sizeof(local));
if (ret < 0)
{
//说明绑定失败
std::cerr << "bind绑定失败" << errno <<std::endl;
return 2;
}
3.接收客户端连接
绑定端口后,现在只需要等待接收来自其他客户端的消息。我们使用recvfrom函数来接收,在接收到数据以后,将收到的信息打印出来。
while (1)
{
char buffer[1024]; //用于存放对方发送的数据
struct sockaddr_in src; //用于保存对端的地址信息
socklen_t len = sizeof(src); //对端地址信息的大小
recvfrom(server, buffer, sizeof(buffer) - 1, 0, (struct sockaddr*)&src, &len);
std::cout << "client# " << buffer << std::endl;
}
4.给客户端发送数据
我们使用的是sendto函数,将数据处理好后发送到客户端。当客户端向我们发起请求的时候,同时
也获取到了客户端的地址信息。
while (1)
{
char buffer[1024]; //用于存放对方发送的数据
struct sockaddr_in src; //用于保存对端的地址信息
socklen_t len = sizeof(src); //对端地址信息的大小
recvfrom(server, buffer, sizeof(buffer)-1 , 0, (struct sockaddr*)&src, &len);
std::cout<< "client# " << buffer << std::endl;
std::string msg = "收到来自客户端的信息:";
msg.append(buffer);
sendto(server, msg.c_str(), msg.size(), 0, (struct sockaddr*)&src, len);
}
二、客户端
1.创建套接字
客户端也需要套接字来承载地址信息,使用的函数也是socket函数
//创建客户端套接字
int client = socket(AF_INET, SOCK_DGRAM, 0);
if(client<0){
std::cerr << "socket创建失败" << std::endl;
return 1;
}
2.填写服务器的地址信息
客户端无需显式的绑定端口号,假设你绑定的端口号为40,然而你并不知道40号端口是否被其他应用程序占用。因此,一般客户端无需显式的绑定端口,绑定端口的任务就交给OS,它最清楚哪个端口没有被占用。
我们需要做的是准备好服务器的地址信息,以用于下面的sendto函数
//客户端要给谁发??
struct sockaddr_in dst;
dst.sin_family = AF_INET;
dst.sin_port = htons(8080); //服务器的端口号
dst.sin_addr.s_addr = inet_addr("*.*.*.*"); //服务器的ip地址
3.从键盘获取内容发送到服务端
while (1)
{
//从键盘获取内容
std::string msg;
std::cout << "client# ";
std::cin >> msg;
//向服务器发送数据
socklen_t len = sizeof(dst);
sendto(client, msg.c_str(), msg.size(), 0, (struct sockaddr*)&dst, len);
char buffer[1024];
//接收服务器做出的响应
int ret = recvfrom(client, buffer, sizeof(buffer)-1, 0, (struct sockaddr*)&dst, &len);
if(ret>0){
std::cout << "server# " << buffer << std::endl;
}
}