相关代码:
//客户端代码
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
const int MAX_LEN = 4096; //缓存区长度
const char serverip[] = "192.168.124.2"; //设置服务器地址 此处为本机地址
const int servercom = 8080; //设置服务器监听端口
const int localcom = 8081; //设置本机端口
int main()
{
int fd; //通信描述符
int count; //接收字节数
char recvbuff[MAX_LEN], sendbuff[MAX_LEN]; //定义接收缓存区和发送缓存区
struct sockaddr_in localaddr;
struct sockaddr_in serveraddr;
socklen_t locallen = sizeof(localaddr);
socklen_t serverlen = sizeof(serveraddr);
//建立UDP的通信文件描述符
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
cout << "creat fd error" << endl;
return -1;
}
//填写服务器地址信息
memset(&serveraddr, 0, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(servercom); //此处转换为网络字节序
//填入服务器的IP并转换为网络字节序
if (inet_pton(AF_INET, serverip, &serveraddr.sin_addr) <= 0)
{
cout << "transf serverip error!" << endl;
return -1;
}
//设定本客户端的地址信息
memset(&localaddr, 0, sizeof(localaddr));
localaddr.sin_family = AF_INET;
localaddr.sin_port = htons(localcom); //此处转换为网络字节序
localaddr.sin_addr.s_addr = htonl(INADDR_ANY); //设置本地IP
//绑定通信描述符和本地地址端口
if ((bind(fd, (struct sockaddr *)&localaddr, locallen)) < 0)
{
cout << "bind fail" << endl;
return -1;
}
cout << "client init successed" << endl;
cout << "port:" << ntohs(localaddr.sin_port)
<< " ip:" << inet_ntoa(localaddr.sin_addr) << endl;
while (1)
{
cout << "input:" << endl;
memset(sendbuff, 0, sizeof(sendbuff)); //清零
cin.getline(sendbuff, MAX_LEN); //等待写入
//向服务器发送数据 从localaddr发到serveraddr
if (sendto(fd, sendbuff, sizeof(sendbuff), 0, (struct sockaddr *)&serveraddr, serverlen) < 0)
{
cout << "send fail!" << endl;
return -1;
}
//从服务器接受消息
count = recvfrom(fd, recvbuff, sizeof(recvbuff), 0, (struct sockaddr *)&serveraddr, &serverlen);
if (count == -1)
{
cout << "receive fail" << endl;
return -1;
}
else
cout << "receive message: " << recvbuff << endl; //显示接收的字符
cout << "clien port:" << ntohs(localaddr.sin_port)
<< " ip:" << inet_ntoa(localaddr.sin_addr) << endl;
cout << "server port:" << ntohs(serveraddr.sin_port)
<< " ip:" << inet_ntoa(serveraddr.sin_addr) << endl;
}
close(fd);
return 0;
}
//服务器端代码
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
const int MAX_LEN = 4096; //缓存区长度
const int servercom = 8080; //服务器端口
int main()
{
int listenfd;
struct sockaddr_in servaddr; //服务器监听信息
struct sockaddr_in clieaddr; //获取客户端地址信息
socklen_t serverlen = sizeof(servaddr);
socklen_t clienlen = sizeof(clieaddr);
char buff[MAX_LEN];
int recv_count = 0;
//建立监听文件描述符
if ((listenfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
{
cout << "creat fd error!" << endl;
return -1;
}
//填入服务器通信地址信息
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY); //地址为任意本机地址
servaddr.sin_port = htons(servercom);
//将地址信息与描述符绑定
if (bind(listenfd, (struct sockaddr *)&servaddr, serverlen) < 0)
{
cout << "bind error!" << endl;
return -1;
}
//必要信息输出
cout << "server init successed!" << endl;
cout << "port:" << ntohs(servaddr.sin_port)
<< " ip:" << inet_ntoa(servaddr.sin_addr) << endl;
cout << "wait for connect!" << endl;
while (1)
{
//等待从clieaddr地址接收数据,监听数据端口为servaddr,同时把客户端信息放在clieaddr中
recv_count = recvfrom(listenfd, buff, MAX_LEN, 0, (struct sockaddr *)&clieaddr, &clienlen);
if (recv_count == -1)
{
cout << "receive data error!" << endl;
return -1;
}
buff[recv_count] = '\0'; //在收到的数据后添加结束符号
cout << "recv msg from client: " << buff << endl; //输出接收的字符
//将原数据发给客户端clieaddr
sendto(listenfd, buff, sizeof(buff), 0, (struct sockaddr *)&clieaddr, clienlen);
//显示客户端的地址和服务端的地址
cout << "clien port:" << ntohs(clieaddr.sin_port)
<< " ip:" << inet_ntoa(clieaddr.sin_addr) << endl;
cout << "server port:" << ntohs(servaddr.sin_port)
<< " ip:" << inet_ntoa(servaddr.sin_addr) << endl;
}
close(listenfd);
return 0;
}
心得:
客户端
1.声明客户端地址、服务器地址
2.建立文件描述符fd
3.填写服务器信息,IP、端口等
4.填写本地信息,主要是端口,并与fd绑定bind(可选,选择后客户端不会再自动选择端口)
5.输入信息,sendto服务器地址信息
6.recvfrom服务器地址信息
服务端
1.声明客户端地址、服务器地址
2.建立文件描述符fd
3.填写服务器信息,IP、端口等
4.将服务器信息与fd绑定bind
5.recvfrom监听服务器端口信息,将得到的数据存入buff,将客户端信息存入客户端地址信息
6.sendto客户端地址将信息发送回客户端
***注意***
如果期望打印相关的地址ip\端口信息需要将其从网络字节序转回主机字节序