这里写自定义目录标题
UDP(user Datagram Protocol)用户数据报协议
int socket (int domain, int type, int protocol);
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
第一个参数就是创建的套接字;第二:要绑定的IP地址和Port, 第三:地址长度
查找:
grep -nFR 'struct sockaddr_in { ' /usr/include/
一、 基于UDP的本地 server 和client 通讯 代码
Makefile
Makefile
.PHONY:all
all:udpClient udpServer
udpClient:udpClient.cc
g++ -o $@ $^ -std=c++11
udpServer:udpServer.cc
g++ -o $@ $^
.PHONY:clean
clean:
rm -f udpClient udpServer
Server.hpp
#pragma once
#include <iostream>
#include <string>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
class udpServer{
private:
std::string ip;
int port;
int sock;
public:
udpServer(std::string _ip="127.0.0.1", int _port=8080)
:ip(_ip), port(_port)
{
}
void initServer()
{
sock = socket(AF_INET, SOCK_DGRAM, 0); //AF_INET:IPV4类型通信; SOCK_DGRAM: 套接字类别,如流式套接字,原始套接字;
//sock的返回值是文件描述符;所以sock相当于之前的Open()
std::cout << "sock: " << sock << std::endl; //默认是3;
//所以创建套接字本质是打开了一个文件;但是当前只有网络文件信息;所以接下来要bind ip和port信息;
struct sockaddr_in local; //绑定是在内核层绑定;
local.sin_family = AF_INET;
local.sin_port = htons(port); //主机序列转为网络序列
local.sin_addr.s_addr = inet_addr(ip.c_str()); //把字符串风格的IP转换成网络IP //ip是string的字符串,所以要转换为char,即用.c_str()
//关于bind 成功返回0,失败<0;
if(bind(sock, (struct sockaddr*)&local, sizeof(local)) < 0){ //注意这里&local 为struct sockadd_in类型, 要强转为 struct sockaddr*
std::cerr << "bind error!\n" << std::endl;
exit(1);
}
}
//echo server 服务器已经创建好了 下面收发消息
void start()
{
char msg[64];
for(;;){
msg[0] = '\0';
struct sockaddr_in end_point;
socklen_t len = sizeof(end_point);
ssize_t s = recvfrom(sock, msg, sizeof(msg)-1,\ //s是读到数据的长度 // (打开的文件, 缓冲区, 期望读多少数据)
0, (struct sockaddr*)&end_point, &len); //最后两个是输出型参数和输入输出型参数,发送方地址, 发送了多长实际接收了多长
if(s > 0){
msg[s] = '\0';
std::cout <<"client# " << msg << std::endl;
std::string echo_string = msg;
echo_string += " [server echo!]";
sendto(sock, echo_string.c_str(), echo_string.size(), 0,\
(struct sockaddr*)&end_point, len);
}
}
}
~udpServer()
{
close(sock);
}
};
Client.hpp
#pragma once
#include <iostream>
#include <string>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
class udpClient{
private:
std::string ip;
int port;
int sock;
public:
//ip,port? server ip,port!!!
udpClient(std::string _ip="127.0.0.1", int _port=8080)
:ip(_ip), port(_port)
{
}
void initClient()
{
sock = socket(AF_INET, SOCK_DGRAM, 0);
std::cout << "sock: " << sock << std::endl;
//客户端不需要bind,但需要IP port ;
// struct sockaddr_in local;
// local.sin_family = AF_INET;
// local.sin_port = htons(port);
// local.sin_addr.s_addr = inet_addr(ip.c_str());
// if(bind(sock, (struct sockaddr*)&local, sizeof(local)) < 0){
// std::cerr << "bind error!\n" << std::endl;
// exit(1);
// }
}
//echo server
void start()
{
// char msg[64];
std::string msg;
struct sockaddr_in peer; //peer 远端
peer.sin_family = AF_INET;
peer.sin_port = htons(port);
peer.sin_addr.s_addr = inet_addr(ip.c_str());
for(;;){
std::cout << "Please Enter# ";
std::cin >> msg;
if(msg == "quit"){
break;
}
//客户端先发消息
sendto(sock, msg.c_str(), msg.size(), 0, (struct sockaddr*)&peer, sizeof(peer));
char echo[128]; //用于存放接收的消息
ssize_t s = recvfrom(sock, echo, sizeof(echo)-1, 0, nullptr, nullptr); //echo:缓冲区
if(s >0){ //发送方
echo[s] = 0;
std::cout << "server# " << echo << std::endl;
}
// msg[0] = '\0';
// struct sockaddr_in end_point;
// socklen_t len = sizeof(end_point);
// ssize_t s = recvfrom(sock, msg, sizeof(msg)-1,\
// 0, (struct sockaddr*)&end_point, &len);
// if(s > 0){
// msg[s] = '\0';
// std::cout <<"client# " << msg << std::endl;
// std::string echo_string = msg;
// echo_string += " [server echo!]";
// sendto(sock, echo_string.c_str(), echo_string.size(), 0,\
// (struct sockaddr*)&end_point, len);
// }
}
}
~udpClient()
{
close(sock);
}
};
Server.cc
#include "udpServer.hpp"
int main()
{
udpServer *up = new udpServer();
up->initServer();
up->start();
delete up;
}
Client.cc
#include "udpClient.hpp"
int main()
{
udpClient uc; //new或者不new都可以 建议new
uc.initClient();
uc.start();
return 0;
}
结果展示:
二、基于UDP协议 简单在线翻译
代码展示
Makefile
FLAG=-std=c++11
.PHONY:all
all:udpClient udpServer
udpClient:udpClient.cc
g++ -o $@ $^ $(FLAG) -static
udpServer:udpServer.cc
g++ -o $@ $^ $(FLAG)
.PHONY:clean
clean:
rm -f udpClient udpServer
server.hpp
#pragma once
#include <iostream>
#include <cstdio>
#include <string>
#include <map>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
class udpServer{
private:
// std::string ip;
int port;
int sock;
std::map<std::string, std::string> dict;
public:
udpServer(int _port=8080)
:port(_port)
{
dict.insert(std::pair<std::string, std::string>("apple", "苹果,是一种水果!"));
dict.insert(std::pair<std::string, std::string>("banana", "香蕉,是一种水果!"));
dict.insert(std::pair<std::string, std::string>("student", "学生"));
}
void initServer()
{
sock = socket(AF_INET, SOCK_DGRAM, 0);
std::cout << "sock: " << sock << std::endl;
struct sockaddr_in local;
local.sin_family = AF_INET;
local.sin_port = htons(port);
//local.sin_addr.s_addr = inet_addr(ip.c_str());
local.sin_addr.s_addr = INADDR_ANY; //表示可以接收任意IP地址
if(bind(sock, (struct sockaddr*)&local, sizeof(local)) < 0){
std::cerr << "bind error!\n" << std::endl;
exit(1);
}
}
//echo server
void start()
{
char msg[64];
for(;;){
msg[0] = '\0';
struct sockaddr_in end_point;
socklen_t len = sizeof(end_point);
ssize_t s = recvfrom(sock, msg, sizeof(msg)-1,\
0, (struct sockaddr*)&end_point, &len);
//分析命令
//fork
//dup2()1, socket
//exec*(cmd)?
if(s > 0){
char buf[16];
sprintf(buf, "%d", ntohs(end_point.sin_port));
std::string cli = inet_ntoa(end_point.sin_addr); //将主机地址转换位点分十进制;
cli += ":";
cli += buf;
msg[s] = '\0';
std::cout << cli << "# " << msg << std::endl;
std::string echo = "unknow";
auto it = dict.find(msg);
if(it != dict.end()){
echo = dict[msg];
}
//echo_string += " [server echo!]";
sendto(sock, echo.c_str(), echo.size(), 0,\
(struct sockaddr*)&end_point, len);
}
}
}
~udpServer()
{
close(sock);
}
};
client.hpp
#pragma once
#include <iostream>
#include <string>
#include <unistd.h>
#include <stdlib.h>+
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
class udpClient{
private:
std::string ip;
int port;
int sock;
public:
//ip,port? server ip,port!!!
udpClient(std::string _ip="127.0.0.1", int _port=8080)
:ip(_ip), port(_port)
{
}
void initClient()
{
sock = socket(AF_INET, SOCK_DGRAM, 0);
std::cout << "sock: " << sock << std::endl;
// struct sockaddr_in local;
// local.sin_family = AF_INET;
// local.sin_port = htons(port);
// local.sin_addr.s_addr = inet_addr(ip.c_str());
// if(bind(sock, (struct sockaddr*)&local, sizeof(local)) < 0){
// std::cerr << "bind error!\n" << std::endl;
// exit(1);
// }
}
//echo server
void start()
{
// char msg[64];
std::string msg;
struct sockaddr_in peer;
peer.sin_family = AF_INET;
peer.sin_port = htons(port);
peer.sin_addr.s_addr = inet_addr(ip.c_str());
for(;;){
std::cout << "Please Enter# ";
std::cin >> msg;
if(msg == "quit"){
break;
}
sendto(sock, msg.c_str(), msg.size(), 0, (struct sockaddr*)&peer, sizeof(peer));
//发送后要接收消息;
char echo[128];
ssize_t s = recvfrom(sock, echo, sizeof(echo)-1, 0, nullptr, nullptr);
if(s >0){
echo[s] = 0;
std::cout << "server# " << echo << std::endl;
}
// msg[0] = '\0';
// struct sockaddr_in end_point;
// socklen_t len = sizeof(end_point);
// ssize_t s = recvfrom(sock, msg, sizeof(msg)-1,\
// 0, (struct sockaddr*)&end_point, &len);
// if(s > 0){
// msg[s] = '\0';
// std::cout <<"client# " << msg << std::endl;
// std::string echo_string = msg;
// echo_string += " [server echo!]";
// sendto(sock, echo_string.c_str(), echo_string.size(), 0,\
// (struct sockaddr*)&end_point, len);
// }
}
}
~udpClient()
{
close(sock);
}
};
server.cc
#include "udpServer.hpp"
8080
void Usage(std::string proc)
{
std::cout << "Usage: " << proc << " port" <<std::endl;
}
//./udpServer ip port
int main(int argc, char *argv[]) // 指针数组
{
if(argc != 2){ //检查合法性;argc表示指针数组的元素个数。这里是2个:./server 8080
Usage(argv[0]);
exit(1);
}
udpServer *up = new udpServer(atoi(argv[1]));
up->initServer();
up->start();
delete up;
}
client.cc
#include "udpClient.hpp"
void Usage(std::string proc)
{
std::cout <<"Usage: "<< proc << " svr_ip svr_port" << std::endl;
}
int main(int argc, char *argv[])
{
if(argc != 3){
Usage(argv[0]);
exit(1);
}
udpClient uc(argv[1], atoi(argv[2]));
uc.initClient();
uc.start();
return 0;
}