当前位置: 首页 > news >正文

特色的佛山网站建设厦门网站建设哪家便宜

特色的佛山网站建设,厦门网站建设哪家便宜,南县网页定制,上海网站seo优化🥁作者: 华丞臧. 📕​​​​专栏:【网络】 各位读者老爷如果觉得博主写的不错,请诸位多多支持(点赞收藏关注)。如果有错误的地方,欢迎在评论区指出。 推荐一款刷题网站 👉 LeetCode刷题网站 文章…

🥁作者华丞臧.
📕​​​​专栏:【网络】
各位读者老爷如果觉得博主写的不错,请诸位多多支持(点赞+收藏+关注)。如果有错误的地方,欢迎在评论区指出。
推荐一款刷题网站 👉 LeetCode刷题网站


文章目录

  • 一、TCP协议
    • 1.1 socket 常见API
      • listen
      • accept
      • connect
    • 1.2 TCP服务器
      • init()
      • start()
    • 1.3 TCP客户端
    • 1.4 测试


一、TCP协议

对TCP(Transmission Control Protocol 传输控制协议)有一个直观的认识:

  • 传输层协议
  • 有连接
  • 可靠传输
  • 面向字节流

1.1 socket 常见API

// 创建 socket 文件描述符 (TCP/UDP, 客户端 + 服务器)
int socket(int domain, int type, int protocol);
  • socket()打开一个网络通讯端口,如果成功的话,就像open()一样返回一个文件描述符;
  • 应用程序可以像读写文件一样用read/write在网络上收发数据;
  • 如果socket()调用出错则返回-1;
  • 对于IPv4, family参数指定为AF_INET;
  • 对于TCP协议,type参数指定为SOCK_STREAM, 表示面向流的传输协议
  • protocol参数的介绍从略,指定为0即可。
// 绑定端口号 (TCP/UDP, 服务器) 
int bind(int socket, const struct sockaddr *address,socklen_t address_len);
  • 服务器程序所监听的网络地址和端口号通常是固定不变的,客户端程序得知服务器程序的地址和端口号后就可以向服务器发起连接; 服务器需要调用bind绑定一个固定的网络地址和端口号;
  • bind()成功返回0,失败返回-1。
  • bind()的作用是将参数sockfd和myaddr绑定在一起, 使sockfd这个用于网络通讯的文件描述符监听
  • myaddr所描述的地址和端口号;
  • 前面讲过,struct sockaddr *是一个通用指针类型,myaddr参数实际上可以接受多种协议的sockaddr结构体,而它们的长度各不相同,所以需要第三个参数addrlen指定结构体的长度;

程序中对 sockaddr 参数是这样初始化的:

#include <netinet/in.h>
#include <arpa/inet.h>// 2.填充域
struct sockaddr_in local;
bzero(&local, sizeof(local));
local.sin_family = AF_INET;
local.sin_port = htons(port_);
  1. 将整个结构体清零;
  2. 设置地址类型为AF_INET;
  3. 网络地址为INADDR_ANY, 这个宏表示本地的任意IP地址,因为服务器可能有多个网卡,每个网卡也可能绑定多个IP 地址, 这样设置可以在所有的IP地址上监听,直到与某个客户端建立了连接时才确定下来到底用哪个IP 地址;
  4. 端口号为SERV_PORT, 我们定义为9999。

listen

// 开始监听socket (TCP, 服务器)
int listen(int socket, int backlog);
  • listen()声明sockfd处于监听状态, 并且最多允许有backlog个客户端处于连接等待状态, 如果接收到更多的连接请求就忽略, 这里设置不会太大(一般是5);
  • listen()成功返回0,失败返回-1。

accept

// 接收请求 (TCP, 服务器)
int accept(int socket, struct sockaddr* address,socklen_t* address_len);
  • 三次握手完成后, 服务器调用accept()接受连接;
  • 如果服务器调用accept()时还没有客户端的连接请求,就阻塞等待直到有客户端连接上来;
  • addr是一个传出参数,accept()返回时传出客户端的地址和端口号;
  • 如果给addr 参数传NULL,表示不关心客户端的地址;
  • addrlen参数是一个传入传出参数(value-result argument), 传入的是调用者提供的, 缓冲区addr的长度
  • 以避免缓冲区溢出问题, 传出的是客户端地址结构体的实际长度(有可能没有占满调用者提供的缓冲区);

connect

// 建立连接 (TCP, 客户端)
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
  • 客户端需要调用connect()连接服务器;
  • connect和bind的参数形式一致, 区别在于bind的参数是自己的地址, 而connect的参数是对方的地址;
  • connect()成功返回0,出错返回-1;

1.2 TCP服务器

在这里插入图片描述

#include <iostream>
#include <stdio.h>
#include <strings.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <pthread.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>#include "Log.hpp"volatile bool quitSer = false;void Usage(void *vgs)
{std::cout << "Usage:./tcpserver port ip" << std::endl;
}
class server
{
public:server(int port, std::string ip = ""): sockfd_(-1), ip_(ip), port_(port){}~server(){}public:void init(){}void start(){}private:int sockfd_;uint16_t port_;std::string ip_;
};// ./tcpserver port ip
int main(int argc, char *argv[])
{if (argc < 2 || argc > 3){Usage(argv[0]);exit(USAGE_ERR);}uint16_t port = atoi(argv[1]);std::string ip;if (argc == 3)ip = argv[2];server tcpSer(port, ip);tcpSer.init();tcpSer.start();return 0;
}

init()

TCP套接字服务器端的 init() ,与UDP类似,只不过多了最后一步监听套接字,TCP套接字设置步骤如下:

在这里插入图片描述

void init()
{// 1. 创建套接字sockfd_ = socket(AF_INET, SOCK_STREAM, 0);if (sockfd_ < 0){logMessage(FATAL, "socket:%s[%d]", strerror(errno), sockfd_);exit(SOCK_ERR);}logMessage(DEBUG, "socket success..");// 2.填充域struct sockaddr_in local;bzero(&local, sizeof(local));local.sin_family = AF_INET;local.sin_port = htons(port_);ip_.empty() ? (local.sin_addr.s_addr = INADDR_ANY) : (inet_aton(ip_.c_str(), &local.sin_addr));// 3. 绑定网络信息if (bind(sockfd_, (const struct sockaddr *)&local, sizeof(local)) < 0){logMessage(FATAL, "bind:%s[%d]", strerror(errno), sockfd_);exit(BIND_ERR);}logMessage(DEBUG, "bind success...");// 4. 监听套接字// 为什么要监听套接字? 因为TCP是面向连接的,在任何时候都可能请求连接 if (listen(sockfd_, 5) < 0){logMessage(FATAL, "listen:%s[%d]", strerror(errno), sockfd_);exit(LISTEN_ERR);}logMessage(DEBUG, "listen success...");// 完成
}

start()

在TCP套接字提供服务之前,需要使用accept获取连接,accept返回值是一个新的套接字文件描述符,使用该套接字文件描述符来进行网络通信。start()是server提供服务的接口,因此该函数必须是一个死循环(服务器都是在一个死循环当中)以给用户提供持续的服务;在start函数中,主要完成接收用户发送的消息并且将消息提取出来,其主要步骤如下图:
在这里插入图片描述

void start()
{char inbuffer_[1024]; // 用来接收客户端发来的消息// 提供服务while (true){quitSer = false;struct sockaddr_in peer;socklen_t len = sizeof(peer);// 5. 获取连接, accept 的返回值是一个新的 socketfdint serviceSock = accept(sockfd_, (struct sockaddr *)&peer, &len);if (serviceSock < 0){// 获取链接失败logMessage(WARINING, "accept: %s[%d]", strerror(errno), serviceSock);continue;}while (!quitSer){memset(inbuffer_, 0, sizeof(inbuffer_));ssize_t s = recvfrom(serviceSock, inbuffer_, sizeof(inbuffer_) - 1, 0,(struct sockaddr *)&peer, &len);if (s > 0){std::cout << s << std::endl;// 接收成功inbuffer_[s] = '\0';}else if (s == -1){//logMessage(WARINING, "recvfrom fialed:%s[%d]", strerror(errno), sockfd_);continue;}uint16_t peerPort = ntohs(peer.sin_port);std::string peerIp = inet_ntoa(peer.sin_addr);if(s > 0)logMessage(NOTICE, "[%s:%d]# %s", peerIp.c_str(), peerPort, inbuffer_);if (strcmp(inbuffer_, "quit") == 0){quitSer = true;}else{sendto(serviceSock, inbuffer_, strlen(inbuffer_), 0,\(const struct sockaddr *)&peer, sizeof(peer)); }}logMessage(DEBUG, "quit server...");close(serviceSock);}
}

1.3 TCP客户端

TCP客户端与UDP不同的是,在进行网络通信之前需要对服务器发起连接请求,连接成功后才能进行网络通信。
在这里插入图片描述

#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cassert>
#include <ctype.h>
#include <unistd.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "Log.hpp"volatile bool quit = false;static void Usage(std::string proc)
{std::cerr << "Usage:\n\t" << proc << " serverIp serverPort" << std::endl;std::cerr << "Example:\n\t" << proc << " 127.0.0.1 8081\n"<< std::endl;
}
// ./clientTcp serverIp serverPort
int main(int argc, char *argv[])
{if (argc != 3){Usage(argv[0]);exit(USAGE_ERR);}std::string serverIp = argv[1];uint16_t serverPort = atoi(argv[2]);// 1. 创建socket SOCK_STREAMint sock = socket(AF_INET, SOCK_STREAM, 0);if (sock < 0){std::cerr << "socket: " << strerror(errno) << std::endl;exit(SOCK_ERR);}// 2. connect,发起连接请求,你想谁发起请求呢??当然是向服务器发起请求喽// 2.1 先填充需要连接的远端主机的基本信息struct sockaddr_in server;memset(&server, 0, sizeof(server));server.sin_family = AF_INET;server.sin_port = htons(serverPort);inet_aton(serverIp.c_str(), &server.sin_addr);// 2.2 发起请求,connect 会自动帮我们进行bind!if (connect(sock, (const struct sockaddr *)&server, sizeof(server)) != 0){std::cerr << "connect: " << strerror(errno) << std::endl;exit(CONN_ERR);}std::cout << "info : connect success: " << sock << std::endl;std::string message;while (!quit){message.clear();std::cout << "请输入你的消息>>> ";std::getline(std::cin, message);if (strcasecmp(message.c_str(), "quit") == 0)quit = true;ssize_t s = write(sock, message.c_str(), message.size());logMessage(DEBUG, "write success...");if (s > 0){message.resize(1024);ssize_t s = read(sock, (char *)(message.c_str()), 1024);if (s > 0)message[s] = 0;std::cout << "Server Echo>>> " << message << std::endl;}else if (s <= 0){break;}}close(sock);return 0;
}

由于客户端不需要固定的端口号,因此不必调用bind(),客户端的端口号由内核自动分配。

注意:

  • 客户端不是不允许调用bind(),只是没有必要调用bind()固定一个端口号。否则如果在同一台机器上启动多个客户端, 就会出现端口号被占用导致不能正确建立连接;
  • 服务器也不是必须调用bind(),但如果服务器不调用bind(),内核会自动给服务器分配监听端口,每次启动服务器时端口号都不一样,客户端要连接服务器就会遇到麻烦。

1.4 测试

在这里插入图片描述

http://www.yayakq.cn/news/861209/

相关文章:

  • 网站建设模块是什么意思产品推广方案设计
  • 海口建站模板厂家杭州小程序设计制作
  • 台州网站制作报价wordpress 翻页 插件
  • 找别人做网站可以提供源码吗给企业做网站的好处
  • 公司网站建设建设网站开发与管理课程设计心得
  • 市场推广专员上海seo网站优化公司
  • 在国外做电商网站有哪些wordpress电台主题
  • 杭州公司网站制作维护wordpress教程 网站标题
  • 制作html购物网站源代码wordpress 图片管理
  • 襄阳建设网站网站建设与管理试卷及答案
  • 郑州做网站网站建设费用站酷网络
  • wordpress做旅游网站什么样的网站
  • 福建网站开发公司网站建设项目策划
  • 广州做网站 信科便宜wordpress上传主题没有反应
  • 烟台免费做网站网页设计与制作教程机械工业出版社
  • 北京移动官方网站南京外贸网站建设怎么收费
  • 凡科网站怎么做建站自己做装修网站需要多少钱
  • 网站建设费包括什么网站推广的方法是什么
  • 网站seo公司即给做网站又给我们做推广的公司呢
  • 中国南昌网站建设企业网站建设市场
  • 只做画册的网站外贸业务推广
  • 深圳建设集团网站首页wordpress添加发布视频教程
  • 江苏城市建设职业学院网站群晖非插件搭建wordpress
  • 湘潭做网站 磐石网络wordpress xml生成免插件
  • 本科专业 网站开发做网站 如何 挣钱
  • 汕头市专注网站建设wordpress如何添加模板文件
  • 做网站的程序员前端开发面试会被问到的一些问题
  • 本地电脑如何做网站服务器公司注册线上服务平台
  • 鹤山做网站公司建设网站包括哪些费用
  • 搭建网站论坛义乌推广公司