网站开发端口查询,哪里做网站公司好,深圳网站建设知了网络,网站开发技术 主流五、UDP网络编程
1.对于服务器使用智能指针维护生命周期#xff1b;2.创建UDP套接字#xff1b;3.绑定端口号#xff0c;包括设置服务器端口号和IP地址#xff0c;端口号一般是2字节使用uint16_t#xff0c;而IP地址用户习惯使用点分十进制格式所以传入的是string类型…五、UDP网络编程
1.对于服务器使用智能指针维护生命周期2.创建UDP套接字3.绑定端口号包括设置服务器端口号和IP地址端口号一般是2字节使用uint16_t而IP地址用户习惯使用点分十进制格式所以传入的是string类型同时要保证网络字节序列4.执行run
5.1使用接口
5.1.1创建套接字
int socket(int domain, int type, int protocol);
//第一个参数为域/协议家族AF_UNIX, AF_LOCAL表示域间套接字AF_INET AF_INET6表示网络套接字AF_PACKET表示原始套接字除了AF开头也可以PF开头
//第二个参数表示socket的类型SOCK_STREAM表示流式套接字SOCK_DGRAM表示数据包套接字
//第三个参数如果只有一个协议则使用0
//返回值是socket文件的文件描述符打开的是网卡设备5.1.2进行绑定
#include sys/types.h
#include sys/socket.h
int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
struct sockaddr {sa_family_t sa_family;char sa_data[14];
}
//第一个参数是创建好的套接字文件描述符
//第二个参数是输入型参数一个特定的结构需要使用其他结构进行强转
//第三个参数特定类型的长度
//返回值成功为0失败为-1错误码被设置#include strings.h
void bzero(void *s, size_t n);
#include string.h
void *memset(void *s, int c, size_t n);
//使用上述函数进行清空typedef uint16_t in_port_t;
typedef uint32_t in_addr_t;
struct in_addr
{in_addr_t s_addr;
};
typedef unsigned short int sa_family_t;
#define __SOCKADDR_COMMON(sa_prefix) \sa_family_t sa_prefix##family
struct sockaddr_in
{__SOCKADDR_COMMON (sin_);in_port_t sin_port; /* Port number. */struct in_addr sin_addr; /* Internet address. *//* Pad to size of struct sockaddr. */unsigned char sin_zero[sizeof (struct sockaddr) -__SOCKADDR_COMMON_SIZE -sizeof (in_port_t) -sizeof (struct in_addr)];
};
sockaddr_in结构中sin表示socket inet
sin_zero表示填充字段
sin_port表示端口号字段
sin_family表示使用的协议家族如AF_INET之类的
sin_addr表示的是IP地址结构
//local.sin_addr.s_addr INADDR_ANY;//任意地址绑定//字符串转整数接口
#include sys/socket.h
#include netinet/in.h
#include arpa/inet.h
int inet_aton(const char *cp, struct in_addr *inp);
in_addr_t inet_addr(const char *cp);//将字符串转32位并且是网络序列的
//整数转字符串
char *inet_ntoa(struct in_addr in);//将整数转为字符串并且将网络字节序转为主机字节序5.1.3数据报的读取
#include sys/types.h
#include sys/socket.h
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);
//第四个参数默认使用0以阻塞方式
ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);5.1.4数据报的发送
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);5.2补充知识
1.查看网络状态
netstat -nlupa
#查看网络状态n表示能显示成数字的就都显示成数字l表示listen u表示udpp表示进程a表示所有2.IP问题
云服务器禁止直接绑定公网IP配置较高的机器IP地址不唯一只是绑定一个IP地址就会导致另一个IP地址的发往另一个IP地址的数据无法被接收一般使用的是0这样凡是发送给本主机的数据都要根据端口号向上交付而不是先确定IP即IP地址使用0表示的是任意地址绑定
3.端口号问题
云服务器端口号默认0-1023是不允许绑定的是系统内定的端口号一般由固定的应用层协议使用如http-80https-443MySQL-3306普通用户直接使用的一般是1024以后的端口号端口号的范围是0-65535可以在这个范围内使用
服务器需要绑定显式端口号但是客户端不需要显式绑定操作系统会随机绑定因为一个端口号只能被一个进程绑定所以重复绑定同一个端口号会出错防止出现这种冲突就不允许用户显示绑定而是交给了操作系统只要保证端口号的唯一性就可以这样就不会导致不同软件的客户端出现绑定端口号冲突一般服务器需要显示绑定端口号是因为一般是客户端先发送的请求所以需要知道服务端的IP地址和端口号且端口号不能发生变化必须是固定的这样才能让客户端知道要发送的另一端进程是谁
系统会在客户端首次发送数据的时候进行端口号的绑定客户端可以获取多个服务器的信息所以获取信息时要包含服务端的信息
4.本地环回地址
127.0.0.1是本地环回地址通常来进行cs的测试
5.3echo服务器实现
服务端
#include sys/types.h
#include sys/socket.h
#include log.hpp
#include string
#include arpa/inet.h
#include cstring
#include cstdlib
#include netinet/in.h
#include functionalusing func_t std::functionstd::string(const std::string );
extern Log lg;const uint16_t defaultport 8080;
const std::string defaultip 0.0.0.0;
const int size 1024;enum
{SOCKETERR 1,BINDERR,
};class udpserver
{public:udpserver(const uint16_t port defaultport, const std::string ip defaultip) : ip_(ip), port_(port), isrunning_(false) {}~udpserver(){if (sockfd_ 0){close(sockfd_);}}public:void init(){// 1.创建socketsockfd_ socket(AF_INET, SOCK_DGRAM, 0);if (sockfd_ 0){lg(Fatal, socket create error, sockfd: %d, sockfd_);exit(SOCKETERR);}lg(Info, socket create success, sockfd: %d, sockfd_);// 2.bindstruct sockaddr_in local;bzero(local, sizeof(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;int n bind(sockfd_, (sockaddr *)local, sizeof(local));if (n 0){lg(Fatal, bind error, errno: %d, strerror: %s, errno, strerror(errno));exit(BINDERR);}lg(Info, bind success, errno: %d, strerror: %s, errno, strerror(errno));}void run(func_t func){isrunning_ true;char buff[size];sockaddr_in client;socklen_t sz sizeof(client);while (isrunning_){ssize_t n recvfrom(sockfd_, buff, sizeof(buff) - 1, 0, (sockaddr *)client, sz);if (n 0){lg(Warning, recvfrom error, errno: %d, strerror: %s, errno, strerror(errno));continue;}buff[n] 0;// 处理数据std::string info buff;std::string echo_string func(info);sendto(sockfd_, echo_string.c_str(), echo_string.size(), 0, (sockaddr *)client, sz);}}private:int sockfd_; // 网络文件描述符std::string ip_; // IP地址1.将字符串风格转换为uint_t类型2.转换成网络字节序列uint16_t port_; // 端口号转换成网络字节序列bool isrunning_;
};--
void Usage(string proc)
{cout \n\rUsage: proc port[1024] endl;
}string handler(const string str)
{cout str endl;string ret server get a message: ;ret str;return ret;
}int main(int argc, char *argv[])
{if (argc ! 2){Usage(argv[0]);exit(0);}uint16_t port stoi(argv[1]);unique_ptrudpserver svr(new udpserver(port, 127.0.0.1));svr-init();svr-run(handler);return 0;
}客户端
#include iostream
#include sys/types.h
#include sys/socket.h
#include cstring
#include cstdlib
#include arpa/inet.h
#include netinet/in.h
#include log.hpp
extern Log lg;void Usage(std::string proc)
{std::cout \n\rUsage: proc serverip serverport\n std::endl;
}
int main(int argc, char *argv[])
{if (argc ! 3){Usage(argv[0]);return 0;}std::string serverip argv[1];uint16_t serverport std::stoi(argv[2]);int sockfd socket(AF_INET, SOCK_DGRAM, 0);if (sockfd 0){std::cerr socket error std::endl;exit(1);}sockaddr_in server;bzero(server, sizeof(server));server.sin_family AF_INET;server.sin_port htons(serverport);server.sin_addr.s_addr inet_addr(serverip.c_str());std::string message;char buff[1024];while (true){std::cout client say ;std::getline(std::cin, message);sendto(sockfd, message.c_str(), message.size(), 0, (sockaddr *)server, sizeof(server));sockaddr_in temp;socklen_t len sizeof(temp);ssize_t n recvfrom(sockfd, buff, sizeof(buff) - 1, 0, (sockaddr *)temp, len);if (n 0){buff[n] 0;std::cout buff std::endl;}}close(sockfd);return 0;
}5.4服务器实现执行指令
#include stdio.h
FILE *popen(const char *command, const char *type);
//是一个封装起来的管道和子进程执行命令的接口会自动建立管道让子进程执行命令并将子进程的执行结果通过管道返回给父进程
//第一个参数是子进程要执行的命令第二个参数是对打开文件的方式读写
//返回值是用来进行获取执行结果的
int pclose(FILE *stream);
char *fgets(char *s, int size, FILE *stream);
//读取一行当读到EOF/空时返回nullptrbool safecheck(const string cmd)
{int issafe false;vectorstring keyword;keyword.push_back(rm);keyword.push_back(mv);keyword.push_back(kill);for (auto e : keyword){auto pos cmd.find(e);if (pos ! string::npos){return issafe;}}issafe true;return issafe;
}string execute(const string cmd)
{if (!safecheck(cmd)){return unsafe;}FILE *fp popen(cmd.c_str(), r);if (fp nullptr){perror(popen error: );return error;}char buff[4096];string ret;while (true){char *res fgets(buff, sizeof(buff), fp);if (res nullptr){break;}ret buff;}cout get a cmd: cmd endl;pclose(fp);return ret;
} Xshell的原理就是远端执行了一个22服务即ssh客户端发送指令服务端进行执行后返回结果 5.5Windows和Linux通信
#includeiostream
#includeWinSock2.h//网络套接字接口#pragma comment(lib,ws2_32.lib)//链接静态库using namespace std;int main()
{cout hello client endl;WSADATA wsd;//创建变量int n WSAStartup(MAKEWORD(2, 2), wsd);//初始化//通信过程WSACleanup();//释放变量return 0;
}#define _WINSOCK_DEPRECATED_NO_WARNINGS 1
#includeiostream
#includeWinSock2.h//网络套接字接口
#includestring#pragma comment(lib,ws2_32.lib)//链接静态库using namespace std;
const uint16_t serverport 8080;
const string serverip 60.205.138.126;
int main()
{cout hello client endl;WSADATA wsd;int n WSAStartup(MAKEWORD(2, 2), wsd);int sockfd socket(AF_INET, SOCK_DGRAM, 0);if (sockfd 0){cout socket error endl;}sockaddr_in server;memset(server, 0, sizeof(server));server.sin_family AF_INET;server.sin_port htons(serverport);server.sin_addr.s_addr inet_addr(serverip.c_str());std::string message;char buff[1024];while (true){std::cout client say ;std::getline(std::cin, message);sendto(sockfd, message.c_str(), message.size(), 0, (sockaddr*)server, sizeof(server));sockaddr_in temp;int len sizeof(temp);int n recvfrom(sockfd, buff, sizeof(buff) - 1, 0, (sockaddr*)temp, len);if (n 0){buff[n] 0;std::cout buff std::endl;}}closesocket(sockfd);WSACleanup();return 0;
}