网站悬挂备案号,某俄文网站,北京建机网站,游戏发卡中心网站源码本项目就是基于TCP网络通信搭建的。
TCP:
客户端#xff1a;socket(),connect().
服务端#xff1a;socket(),bind(),listen(),accept(). 下面代码就是对原生API网络套接字的封装。需要熟悉原生API网络套接字接口。
下面这段代码#xff0c;没什么好讲的#xff0c;就不…本项目就是基于TCP网络通信搭建的。
TCP:
客户端socket(),connect().
服务端socket(),bind(),listen(),accept(). 下面代码就是对原生API网络套接字的封装。需要熟悉原生API网络套接字接口。
下面这段代码没什么好讲的就不再讲了。下面代码会涉及文件描述符的相关设置我会专出一篇文章进行讲解。
#define MAX_LISTEN 1024
class Socket {private:int _sockfd;public:Socket():_sockfd(-1) {}Socket(int fd): _sockfd(fd) {}~Socket() { Close(); }int Fd() { return _sockfd; }//创建套接字bool Create() {// int socket(int domain, int type, int protocol)_sockfd socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if (_sockfd 0) {ERR_LOG(CREATE SOCKET FAILED!!);return false;}return true;}//绑定地址信息bool Bind(const std::string ip, uint16_t port) {struct sockaddr_in addr;addr.sin_family AF_INET;addr.sin_port htons(port);addr.sin_addr.s_addr inet_addr(ip.c_str());socklen_t len sizeof(struct sockaddr_in);// int bind(int sockfd, struct sockaddr*addr, socklen_t len);int ret bind(_sockfd, (struct sockaddr*)addr, len);if (ret 0) {ERR_LOG(BIND ADDRESS FAILED!);return false;}return true;}//开始监听bool Listen(int backlog MAX_LISTEN) {// int listen(int backlog)int ret listen(_sockfd, backlog);if (ret 0) {ERR_LOG(SOCKET LISTEN FAILED!);return false;}return true;}//向服务器发起连接bool Connect(const std::string ip, uint16_t port) {struct sockaddr_in addr;addr.sin_family AF_INET;addr.sin_port htons(port);addr.sin_addr.s_addr inet_addr(ip.c_str());socklen_t len sizeof(struct sockaddr_in);// int connect(int sockfd, struct sockaddr*addr, socklen_t len);int ret connect(_sockfd, (struct sockaddr*)addr, len);if (ret 0) {ERR_LOG(CONNECT SERVER FAILED!);return false;}return true;}//获取新连接int Accept() {// int accept(int sockfd, struct sockaddr *addr, socklen_t *len);int newfd accept(_sockfd, NULL, NULL);//不需要获取客户端信息 就可以将他们置NULLif (newfd 0) {ERR_LOG(SOCKET ACCEPT FAILED!);return -1;}return newfd;}//接收数据ssize_t Recv(void *buf, size_t len, int flag 0) {// ssize_t recv(int sockfd, void *buf, size_t len, int flag);ssize_t ret recv(_sockfd, buf, len, flag);if (ret 0) {//EAGAIN 当前socket的接收缓冲区中没有数据了在非阻塞的情况下才会有这个错误//EINTR 表示当前socket的阻塞等待被信号打断了if (errno EAGAIN || errno EINTR) {return 0;//表示这次接收没有接收到数据}ERR_LOG(SOCKET RECV FAILED!!);return -1;}return ret; //实际接收的数据长度}ssize_t NonBlockRecv(void *buf, size_t len) {return Recv(buf, len, MSG_DONTWAIT); // MSG_DONTWAIT 表示当前接收为非阻塞。}//发送数据ssize_t Send(const void *buf, size_t len, int flag 0) {// ssize_t send(int sockfd, void *data, size_t len, int flag);ssize_t ret send(_sockfd, buf, len, flag);if (ret 0) {if (errno EAGAIN || errno EINTR) {return 0;}ERR_LOG(SOCKET SEND FAILED!!);return -1;}return ret;//实际发送的数据长度}ssize_t NonBlockSend(void *buf, size_t len) {if (len 0) return 0;return Send(buf, len, MSG_DONTWAIT); // MSG_DONTWAIT 表示当前发送为非阻塞。}//关闭套接字void Close() {if (_sockfd ! -1) {close(_sockfd);_sockfd -1;}}//创建一个服务端连接bool CreateServer(uint16_t port, const std::string ip 0.0.0.0, bool block_flag false) {//1. 创建套接字2. 绑定地址3. 开始监听4. 设置非阻塞 5. 启动地址重用if (Create() false) return false;if (block_flag) NonBlock();if (Bind(ip, port) false) return false;if (Listen() false) return false;ReuseAddress();return true;}//创建一个客户端连接bool CreateClient(uint16_t port, const std::string ip) {//1. 创建套接字2.指向连接服务器if (Create() false) return false;if (Connect(ip, port) false) return false;return true;}//设置套接字选项---开启地址端口重用void ReuseAddress() {// int setsockopt(int fd, int leve, int optname, void *val, int vallen)int val 1;setsockopt(_sockfd, SOL_SOCKET, SO_REUSEADDR, (void*)val, sizeof(int));val 1;setsockopt(_sockfd, SOL_SOCKET, SO_REUSEPORT, (void*)val, sizeof(int));}//设置套接字阻塞属性-- 设置为非阻塞void NonBlock() {//int fcntl(int fd, int cmd, ... /* arg */ );int flag fcntl(_sockfd, F_GETFL, 0);fcntl(_sockfd, F_SETFL, flag | O_NONBLOCK);}
};