《Linux网络开发必学教程》2_服务端编程初体验

客户端/服务端 编程模式

  • 服务端长期保留于网络(公开自己的 IP 地址),并等待客户端连接
  • 客户端发起连接动作,并等待服务端回应
  • 特点:
    • 服务端无法主动连接客户端
    • 客户端只能按照预定义的方式(协议)连接服务端
服务端编程模式
1. 准备网络连接 2. 绑定端口 3. 进入端口监听状态 4. 等待连接

《Linux网络开发必学教程》2_服务端编程初体验
文章图片

服务端核心工作:绑定 & 监听 & 接收
  • 绑定:int bind(int sock, struct sockaddr *addr, socklen_t addrlen);
  • 监听:int listen(int sock, int backlog);
  • 接收:int accept(int sock, struct sockaddr *addr, socklen_t addrlen);
深度剖析服务端
  • 服务端 socket 只用于接收连接,不进行实际通讯
  • 当接收到连接时,accept() 函数返回与客户端通信的 socket
  • 服务端 socket 产生用于通讯的客户端 socket
所以,socket 究竟是什么玩意?如何理解?
深入理解 socket() 函数
  • socket() 是什么?
    • socket() 是一个多功能函数
  • socket() 返回的又是什么?
    • socket() 的返回值是用于通讯的资源标识符
  • socket() 还能做什么?
    • socket() 可提供不同类型的通讯功能(本地进程间通讯)
编程实验:服务端编程初体验
#include #include #include #include #include #include #include int main() { int server = 0; struct sockaddr_in saddr = {0}; int clinet = 0; struct sockaddr_in caddr = {0}; socklen_t asize = 0; int len = 0; char buf[32] = {0}; int r = 0; server = socket(PF_INET, SOCK_STREAM, 0); if (server == -1) { printf("server socket error\n"); return -1; }saddr.sin_family = AF_INET; saddr.sin_addr.s_addr = htonl(INADDR_ANY); saddr.sin_port = htons(8899); if (bind(server, (struct sockaddr*)&saddr, sizeof(saddr)) == -1) { printf("server bind error\n"); return -1; }if (listen(server, 1) == -1) { printf("server listen error\n"); return -1; }printf("server start success\n"); asize = sizeof(caddr); clinet = accept(server, (struct sockaddr*)&caddr, &asize); if (clinet == -1) { printf("client accept error\n"); return -1; }printf("client: %d\n", clinet); len = 0; do { int i = 0; r = recv(clinet, buf, sizeof(buf), 0); if (r > 0) { len += r; }for (i=0; i

客户端/服务端 编程的核心模式
  • 服务端长时间运行(死循环)接收客户端的请求
  • 客户端连接后向服务端发送请求(协议数据)
【《Linux网络开发必学教程》2_服务端编程初体验】《Linux网络开发必学教程》2_服务端编程初体验
文章图片

服务端核心编程模式
《Linux网络开发必学教程》2_服务端编程初体验
文章图片

编程实验:客户端/服务端编程实验
  1. 服务端持续监听客户端连接
  2. 服务端被连接后 echo 客户端数据
  3. 服务端接收到 quit 后断开连接
  4. 客户端接收用户输入并发送到服务端
服务端
#include #include #include #include #include #include #include int main() { int server = 0; struct sockaddr_in saddr = {0}; int client = 0; struct sockaddr_in caddr = {0}; socklen_t asize = 0; int len = 0; char buf[32] = {0}; int r = 0; server = socket(PF_INET, SOCK_STREAM, 0); if (server == -1) { printf("server socket error\n"); return -1; }saddr.sin_family = AF_INET; saddr.sin_addr.s_addr = htonl(INADDR_ANY); saddr.sin_port = htons(8888); if (bind(server, (struct sockaddr*)&saddr, sizeof(saddr)) == -1) { printf("server bind error\n"); return -1; }if (listen(server, 1) == -1) { printf("server listen error\n"); return -1; }printf("server start success\n"); while (1) { asize = sizeof(caddr); client = accept(server, (struct sockaddr*)&caddr, &asize); if (client == -1) { printf("client accept error\n"); return -1; }printf("client: %d\n", client); do { r = recv(client, buf, sizeof(buf), 0); if (r > 0) { printf("Receive: %s\n", buf); if (strcmp(buf, "quit") != 0) { len = send(client, buf, r, 0); } else { break; } } } while (r > 0); close(client); }close(server); return 0; }

客户端
#include #include #include #include #include #include #include int main() { int sock = 0; struct sockaddr_in addr = {0}; int len = 0; char buf[128] = {0}; char input[32] = {0}; int r = 0; sock = socket(PF_INET, SOCK_STREAM, 0); if (sock == -1) { printf("socket error\n"); return -1; }addr.sin_family = AF_INET; addr.sin_addr.s_addr = inet_addr("192.168.2.46"); addr.sin_port = htons(8888); if (connect(sock, (struct sockaddr*)&addr, sizeof(addr)) == -1) { printf("connect error\n"); return -1; }printf("connect success\n"); while (1) { printf("Input: "); scanf("%s", input); len = send(sock, input, strlen(input) + 1, 0); r = recv(sock, buf, sizeof(buf), 0); if (r > 0) { printf("Receive: %s\n", buf); } else { break; } }close(sock); return 0; }

思考:如何增强服务端能力,同时支持多个客户端?

    推荐阅读