一个Linux TCP服务器程序的实现

一. 前言

        本文将介绍一个简单 Linux TCP 服务器程序的实现,功能是只要客户端发送连接请求过来,就发送"Hello World"给客户端。

二. 基本概念

套接字

        在 TCP/IP 协议中,"IP+端口" 可以唯一标识网络通讯中的一个进程。套接字(socket)本身有插座的意思,它是用于进程间网络通讯的一种特殊文件类型,这种文件跟普通文件不一样,普通文件需要存储在硬盘上,而 socket 文件是借助内核缓冲区形成的伪文件。在 Linux 读写普通文件时,我们先使用 open 函数打开文件然后获取文件句柄 fd,然后调用 read 函数就可以读取文件内容,调用 write 函数就可以往文件写入内容。socket 也可以类似理解为这样的文件描述符,可以理解为:如果网络通讯中两个进程要通讯就需要借助套接字(socket)来实现。

        假设现在服务器创建了一个 socket 并且处于监听状态,客户端也创建了一个 socket 与服务器建立起连接,然后客户端就可以通过 write 给服务器发送数据,通过 read 读取服务器发送来的数据。

CS模型

        C/S 模型又称为客户端/服务器模型,对于 TCP 客户端/服务器模型开发一般如下图所示。

三. Linux TCP服务器程序实现

  1 #include <sys/types.h>
  2 #include <sys/socket.h>
  3 #include <string.h>
  4 #include <netinet/in.h>
  5 #include <arpa/inet.h>
  6 #include <unistd.h>
  7 #include <stdio.h>
  8 
  9 #define SERVER_PORT 8080
 10 
 11 int main()
 12 {
 13     int listen_fd = socket(AF_INET,SOCK_STREAM,0);
 14     int conn_fd = 0;
 15     char data[] = "Hello World!";
 16 
 17     struct sockaddr_in server_addr;
 18     memset(&server_addr,0,sizeof(server_addr));
 19     server_addr.sin_family = AF_INET;
 20     server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
 21     server_addr.sin_port = htons(SERVER_PORT);
 22     
 23     bind(listen_fd,(struct sockaddr *)&server_addr,sizeof(server_addr));
 24     listen(listen_fd,32);
 25     
 26     while(1)
 27     {
 28         conn_fd = accept(listen_fd,(struct sockaddr *)NULL,NULL);
 29         write(conn_fd,data,strlen(data));
 30         close(conn_fd);
 31     }
 32     close(listen_fd);
 33
 34     return 0;
 35 }

程序讲解

1. 首先调用一个 socket 函数创建一个监听套接字,第一个参数 AF_INET 代表是 IPv4 地址,第二个参数 SOCK_STREAM 代表流式协议,第三个参数 0 代表默认协议,这里是 TCP。

2. 将套接字与具体的 IP 和端口绑定,需要调用 bind 函数,bind 函数的第一个参数是需要绑定的 socket,第二个参数是一个 struct sockaddr 类型的指针,第三个参数是 struct sockaddr 类型的指针指向的数据长度。可以看到,创建了 struct sockaddr_in 结构体后,将其程序 sin_family 指定为 AF_INET,即 IPv4 类型;将 sin_addr.s_addr 指定为 INADDR_ANY 代表使用主机的任意一个地址(因为一个电脑可以有多个网卡,拥有多个 IP 地址);将 sin_port 指定为 8080,这样该套接字就与一个本地 IP 和 8080 端口绑定起来了。

3.调用 listen 函数指定处于连接就绪队列的连接数最大值。

4.在 while(1) 中 accept 阻塞等待客户端发送连接请求过来,一旦成功与客户端连接,accept 函数就返回一个与客户端通讯的通讯套接字(注意监听套接字与通讯套接字不同),然后往通讯套接字写入数据,再调用 close 关闭连接。

关于上述一些 API 的具体含义将会在后续文章做深入讲解,这里只需要先简单了解含义即可。

四. 功能调试

编写完 server.c 文件后,需要编译产生可执行文件然后运行。

编译:gcc server.c -o server

运行:./server

运行 server 程序后,需要有对应的客户端程序去发起访问,这里介绍一个好用的客户端工具:telnet。

Ubuntu 下安装 telnet:sudo apt-get install telnet

telnet 使用,在命令行模式下输入:telnet IP地址 端口,如 telnet 127.0.0.1 8080 就可以发起对本地 8080 端口的访问了。

如上,使用 telnet 往 127.0.0.1 的 8080 端口建立连接后,客户端收到了 Hello,world!,这句话是服务器程序 write 函数调用的结果,然后显示 Connection closed by foreign ost,这是因为每次连接后服务器发送完 Hello,world! 就 close 掉这个 socket 了。

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

椛茶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值