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

一. 前言

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

二. 基本概念

套接字

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

一个Linux TCP服务器程序的实现_第1张图片

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

CS模型

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

一个Linux TCP服务器程序的实现_第2张图片

三. Linux TCP服务器程序实现

  1 #include 
  2 #include 
  3 #include 
  4 #include 
  5 #include 
  6 #include 
  7 #include 
  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 了。

你可能感兴趣的:(Linux编程,Linux,服务器,telnet,socket)