问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

如何实现在Linux下创建服务程序

发布网友 发布时间:2022-04-20 17:19

我来回答

2个回答

热心网友 时间:2022-04-14 19:17

Linux系统能提供强大可靠的网络服务,并有管理程序对服务进行管理。例如我们熟悉的Web、FTP和电子邮件等,它们既可以单独运行,也可以被守护进程inetd调用,而且运行得都非常好。但我们不能仅停留在赞叹中,下面就给出两个服务程序程序和一个客户程序的例子,介绍服务程序和客户程序之间是如何沟通的。另外还要编辑配置一些文件,让服务程序也能接受服务管理程序管理。

这两个服务程序功能相同,但一个是独立服务程序,另一个是被inetd调用的服务程序。这是TCP/IP网络服务的两大类,这里将两个程序放在一起是为了比较程序结构和运行方式。两服务程序都在Red Hat Linux 7.1和TurboLinux 7.0上调试通过。

独立服务器

TCP和UDP是两大TCP/IP数据传输方式,套接口是建立服务器客户机连接的机制,首先介绍它们建立通信联系的过程,然后给出一个TCP服务程序例子。

1.TCP套接口通信方式

对于TCP服务器端,服务程序首先调用建立套接口的函数socket(),然后调用绑定服务IP地址和协议端口号函数bind()。绑定成功后调用被动监听函数listen()等待客户连接,还要调用获取连接请求函数accept(),并一直阻塞到客户连接请求的到达,这个函数获取客户机IP地址和协议端口号。

对于TCP客户端,客户程序启动后后调用建立套接口函数socket(),然后调用连接函数connect(),此函数与服务器通过三次握手建立连接。

服务器和客户机建立连接后,就可以使用读函数read()和写函数write()收发数据了。数据交换完成后便各自调用关闭套接口函数close()删除套接口。TCP套接口通信方式见图1所示。

图1 TCP套接口通信方式

2.UDP套接口通信方式

UDP程序与TCP的区别是无需建立连接。服务器首先启动,然后等待用户请求。客户机启动后便直接向服务器请求服务,服务器接到请求后给出应答。

对于UDP服务器端,服务程序首先调用套接口函数socket(),然后调用绑定IP地址和协议端口号函数bind()。之后调用函数recvfrom()接收客户数据,调用sendto()向客户发送数据。

对于UDP客户端,客户机程序启动后调用套接口函数socket(),然后调用sendto()向服务器发送数据,调用recvfrom()接收服务器数据。

双方数据交换成功后,各自调用关闭套接口函数close()关闭套接口。UDP套接口通信方式见图2所示。

图2 UDP套接口通信方式

下面给出独立服务程序的例子。这个程序虽然简单,但是与复杂程序有着相同的结构。

//程序名:server.c
//功能:服务器从客户机读入一个字符,并将排在此字符后面的字符回送客户机
//服务器端口:9000
#include "sys/types.h"
#include "sys/socket.h"
#include "stdio.h"
#include "netinet/in.h"
#include "arpa/inet.h"
#include "unistd.h"
int main()
{
int pid; //用于存放fork()执行结果
int server_sockfd,client_sockfd; //用于服务器和客户机套接口描述符
int bind_flag,listen_flag; //用于存放bind()和listen()执行结果
int server_address_length,client_address_length; //作为服务器客户机地址长变量
struct sockaddr_in server_address; //作为服务器地址结构变量(含地址和端口)
struct sockaddr_in client_address; //作为客户机地址结构变量(含地址和端口)
if((pid=fork())!=0) //用fork()产生新进程
exit(0) ;
setsid() ; //以子进程开始下面的程序

函数socket(),创建一个套接口,成功则返回套接口描述符。

server_sockfd=socket(AF_INET,SOCK_STREAM,0);
if(server_sockfd<0)
{
printf(“socket error /n”);
exit(1);
}
server_address.sin_family=AF_INET;

函数htonl()用于将32位主机字节顺序转换为网络字节顺序,其中参数INADDR_ANY表示任何IP地址。

server_address.sin_addr.s_addr=htonl(INADDR_ANY);

函数htons()用于将16位主机字节顺序转换为网络字节顺序,其中的参数是绑定的端口号,读者可根据环境自行改动,目的是不与其它服务端口冲突。

server_address.sin_port=htons(9000);
server_address_length=sizeof(server_address);

函数bind()用于绑定本地地址和服务端口号,若调用成功返回值为0。

bind_flag=bind(server_sockfd,/
(struct sockaddr *)&server_address,/
server_address_length);
if(bind_flag<0)
{
printf(“bind error /n”);
exit(1);
}

函数listen(),指明服务器的队列长度,被动等待客户连接,调用成功返回值为0。

listen_flag=listen(server_sockfd,5);
if(listen_flag<0)
{
printf(“listen error /n”);
exit(1);
}

while(1)
{
char ch;

函数accept()等待和获取用户请求,为每个新连接请求创建一个新的套接口,调用成功返回新套接口描述符。

client_sockfd=accept(server_sockfd,/
(struct sockaddr *)&client_address,/
&client_address_length);

函数read()和write()用于在服务器和客户机之间传送数据,调用成功返回读和写的字节数。

函数close(),用于程序使用完一个套接口后关闭套接口,调用成功返回值0。其中的参数为accept()创建的套接口的描述符client_sockfd。

read(client_sockfd,&ch,1);
printf(“cli_ch=%c”,ch);
ch++;
write(client_sockfd,&ch,1);

close(client_sockfd);
}
}

程序完成后就可以使用命令进行编译。在命令行中输入“gcc -o server server.c”,将server.c编译成可执行程序server,这时便可用客户程序进行测试。在命令行执行“./server”启动服务程序,执行“netstat -na”查看有无server的服务端口。如果存在,则执行下面编写的客户程序“./client”。不过这仅是手工启动的方法,下面给出用服务管理程序管理server程序的方法。只要在目录/etc/rc.d/init.d下放入服务程序的脚本就能被服务程序读到。在命令行执行“touch server”创建文件server,并将文件属性改成可执行。在管理程序中并不能看到此服务名,脚本文件必须有一些结构才能被管理程序认为是服务程序脚本。

为了减少工作量,拷贝/etc/rc.d/init.d下脚本httpd,将拷贝脚本名命名为server,然后对其编辑。

(1)执行“cp httpd server”。

(2)用文本编辑器vi(其它编辑器亦可)将server打开进入编辑状态。首先用字符串server替换httpd。然后找到daemon server行,如果编写的程序放在变量PATH目录中,不需要修改此行;如果把服务程序放在其它目录中,就要写服务的全路径。例如程序在/root的目录中,就要写成daemon /root/server,还要删除“rm -f /var/run/server.pid”这一行。

(3)执行“chmod 755 server”,将server属性设定为可执行。

此时就可以用chkconfig、ntsysv等工具,在希望的运行级中增加这个新服务程序,然后测试客户机与服务器能否通信。

被xinetd调用的服务程序

在Linux系统中,有很多服务是被xinetd(较早版本使用的是inetd)超级守护服务器启动的。其实凡是基于TCP和UDP的服务都可使用超级守护进程启动,只是在服务量很大影响效率的情况下不被采用。

1.依赖xinetd启动的服务建立通信过程

为了与独立服务器程序比较,我们看一下依赖xinetd的服务器是如何启动的。

(1)xinetd启动时读取/etc/xinetd目录中的文件(早期版本为/etc/inetd文件),根据其中的内容给所有允许启动的服务创建一个指定类型的套接口,并将套接口放入select()中的描述符集合中。

(2)对每个套接口绑定bind(),所用的端口号和其它参数来自/etc/xinetd目录下每个服务的配置文件。

(3)如果是TCP套接口就调用函数listen(),等待用户连接。如果是UDP套接口,就不需调用此函数。

(4)所有套接口建立后,调用函数select()检查哪些套接口是活动的。

(5)若select()返回TCP套接口,就调用accept()接收这个连接。如果为UDP,就不需调用此函数。

(6)xinetd调用fork()创建子进程,由子进程处理连接请求。

◆ 子进程关闭所有其它描述符,只剩下套接口描述符。这个套接口描述符对于TCP是accept()返回的套接口,对于UDP为最初建立的套接口。然后子进程连续三次p()函数,将套接口描述符复制到0、1和2,它们分别对应标准输入、标准输出和标准错误输出,并关闭套接口描述符。

◆ 子进程查看/etc/xinetd下文件中的用户,如果不是root用户,就用调用命令setuid和setgid将用户ID和组ID改成文件中指定的用户。

(7)对于TCP套接口,与用户交流结束后父进程需要关闭已连接套接口。父进程重新处于select()状态,等待下一个可读的套接口。

最后调用配置文件中指定的外部服务程序,外部程序启动后就可与用户进行信息传递了。

2.为xinetd编写专门的服务程序

除了独立服务程序能被xinetd启动外,还可以为xinetd编写专门的程序。此处的例子程序与上面server.c功能相同。不过两者的程序区别是很大的,此例的代码仅相当于上面传输数据的部分。我们还将程序名定为server.c,所以不能放在相同目录中,同名仅是为了和上面程序对照。

#include "unistd.h"
int main()
{
char ch;
read(0,&ch,1);
ch++;
write(1,&ch,1);
}

将程序编译成可执行文件,并做些设置就可被xinetd启动。注意不要和上面的独立服务程序server一起启动,因为客户程序写得比较简单,访问的是固定端口,服务器都设成了相同的端口号。

(1)编辑/etc/services文件,在行末增加一条记录:

server 9000/tcp

(2)在目录/etc/xinetd.d下编写文件server,内容为:

service server
{
disable = no
socket_type = stream
protocol = tcp
wait = no
user = root
server = /home/test/server (此处设置成自己程序所在的目录)
}

如果使用的是较早版本,则需在/etc/inetd.conf文件中添加下面的行:

server tcp nowait root /path/to/yourdirectory/server

(3)执行/etc/rc.d/initd.d/xinetd restart重新启动xinetd服务器。早期版本执行/etc/rc.d/initd.d/inetd restart重新启动inetd。

(4)执行netstat -an查看有没有server程序使用的端口号,如果有就可使用下面客户机程序进行测试了。

客户机程序

下面就客户机函数做一简单介绍。

//程序名client.c
/*功能:从客户的控制台输入一个字符,然后将这个字符送到服务器,并将服务器返回的字符显示出来*/
#include "sys/types.h"
#include "sys/socket.h"
#include "stdio.h"
#include "netinet/in.h"
#include "arpa/inet.h"
#include "unistd.h"
int main()
{
int sockfd;//
int address_len;
int connect_flag;
struct sockaddr_in address;
int connect_result;
char client_ch,server_ch;

函数socket()用于建立一个套接口,创建成功返回套接口描述符。

sockfd=socket(AF_INET,SOCK_STREAM,0);
if(sockfd<0)
{
printf(“sockfd error /n”);
}
address.sin_family=AF_INET;
address.sin_addr.s_addr=inet_addr(“192.168.0.1”);/*读者根据自己环境改成服务器地址*/
address.sin_port=htons(9000);

address_len=sizeof(address);

函数connect()用于与服务器建立一个主动连接,调用成功返回值为0。

connect_flag=connect(sockfd,(struct sockaddr *)&address,address_len);

if(connect_flag==-1)
{
perror(“client”);
exit(1);
}
printf(“Input a character :”);

函数scanf()用于从控制台输入一个字符,并将字符存入client_ch的地址。函数write()和read()用于传输数据。函数printf()在客户机屏幕上显示服务器传回的字符。函数close()关闭套接口。

scanf(“%c”,&client_ch);
write(sockfd,&client_ch,1);
read(sockfd,&server_ch,1);
printf(“character from server : %c/n”,server_ch);
close(sockfd);
exit(0);
}

执行命令“gcc -o client client.c”,将client.c编译成client。执行“./client”,在程序提示下输入一个字符,就能看到服务器传回的字符。

以上介绍的仅是简单的例子。平时见到的服务程序远比它复杂,而且很多是多协议服务程序或是多协议多服务程序。多协议服务程序就是在main()中分别创建供服务的TCP和UDP套接口。为每个服务分别写出相应程序好处是便于控制,但是这样每个服务都启动两个服务器,而它们的算法响应是一样的,就要耗费不必要的资源,并且出了问题排错也较困难。多服务是将不同的服务集成在一起由一个程序完成,可用一个数组表示服务,数组中的每一项表示某协议某服务的一种,这样很容易扩展程序的服务功能。

热心网友 时间:2022-04-14 20:35

用B/S或者C/S等,以及WebSerice等模式。 服务还是在Windows上,而使用者在Linux上。没有必要非要把服务和使用者放在同一个平台。具体介绍参考《Linux就该这么学》。
如何将Linux注册为服务linux注册为服务

sudo systemctl start my-service.service systemctl也提供了一些其它有用的命令,比如停止和重启服务:sudo systemctl stop my-service.service sudo systemctl restart my-service.service 在服务执行过程中,你可以使用以下命令来查看服务的状态:sudo systemctl status my-service.service 以上就是将Linux...

Linux环境搭建与基本指令(手把手带你在Linux部署项目)

第一步,更改 /etc/my.cnf.d/client.cnf 文件 输入命令vim /etc/my.cnf.d/client.cnf,在插入模式下,在[client] 下加一行配置 default-character-set=utf8mb4,esc退出插入模式,输入:wq保存。 最终内容##Thesetwogroupsarereadbytheclientlibrary#Useitforoptionsthataffectallclients,butnottheserver#[client]defa...

如何在Linux下搭建apache服务器

1、配置防火墙,开启80端口、3306端口 vi /etc/sysconfig/iptables -A INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT #允许80端口通过防火墙 -A INPUT -m state --state NEW -m tcp -p tcp --dport 3306 -j ACCEPT #允许3306端口通过防火墙 备注:很多网友把这两...

怎么在linux下搭建一个nginx服务器

Winxp系统的电脑怎么搭建Nginx WEB服务器具体方法如下:1、下载Nginx程序包,仅有1M左右大小,相当小巧功能强大!2、将下载好的zip压缩包的文件全部解压,双击运行nginx.exe,你会看到一个黑色窗口一闪而过就没了,这就说明Nginx服务器已经正式启动(没有程序界面的)。3、在浏览器输入访问 127.0.0.1 回...

Linux下如何配置C语言开发环境linux配置c环境

1、首先,安装GCC(GNU Compiler Collection):GCC是一个多语言编译器,可以用来编译C / C++等语言。可以使用以下命令在Linux系统上安装GCC:sudo apt-get install gcc 2、安装调试器:为了调试源代码,需要安装GNU调试器(GDB),可以使用以下命令来安装GDB:sudo apt-get install gdb 3、安装库:使用...

如何借助vsftpd在Linux上构建安全的FTP服务

只要建立了匿名FTP连接,会话总是默认使用/var/ftp目录。所以,我们可以将该目录用作FTP公众用户的主目录。放在/var/ftp下面的任何文件/目录都可以通过ftp://[ServerName/IP]加以访问。vsftpd配置文件的位置出现在下面两个地方:•Ubuntu、Debian或Linux Mint:/etc/vsftpd.conf•CentOS、Fedora或RHEL:/etc/vsftpd/...

linux程序安装后调用方法

1 Linux创建自启动程序 自启动有两种方法,都经过自己测试。 1.1 自启动程序方法1: 1.2 自启动程序方法2: 创建Linux服务,步骤如下: 1) 写服务启动脚本文件(后附例子) 2) 修改脚本文件chmod 777 autoruntest 3) 脚本文件拷贝到 /etc/rc.d/init.d/ 4) chkconfig --add autoruntest 添加服务 5) 重新启动(...

如何搭建Linux下的c/s开发模式?

在客户服务器架构的应用中,前台程序不是非常“瘦小”,麻烦的事情都交给了服务器和网络。在C/S体系的下,数据库不能真正成为公共、专业化的仓库,它受到独立的专门管理。 (3)、C/S架构的劣势是高昂的维护成本且投资大。 首先,采用C/S架构,要选择适当的数据库平台来实现数据库数据的真正“统一”,使分布于两地的...

想写个程序在Linux服务器上运行,不熟悉Linux,会一点C、C++、java,要怎 ...

linux 上 写C,C++,Java的服务程序都是可以的,当然,C、C++的执行效率是最高的,我的建议是,如果是C/S模式的应用,用C,C++;如果是Web相关的应用,用Java。这就要看你自己的需求了。

Linux如何配置网络游戏服务器?

要建立一个安全Linux服务器就首先要了解Linux环境下和网络服务相关的配置文件的含义及如何进行安全的配置。在Linux系统中,TCP/IP网络是通过若干个文本文件进行配置的,也许你需要编辑这些文件来完成联网工作,但是这些配置文件大都可以通过配置命令linuxconf(其中网络部分的配置可以通过netconf命令来实现)命令来实现。下面介绍...

ug如何快速创建程序组 自己如何创建小程序 创建程序的一般过程 用于创建对象的程序是excel 创建应用程序 创建程序组什么意思 创建vb应用程序三个主要步骤 算法是程序的具体实现 程序是算法的一种具体实现
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
苏州一级建造师能买吗? 我是苏州2013一级建造师考生,9月15日最后一门考试把身份证忘在课桌上... 二级建造师 报名 现场确认些什么 会不会问你工作内容什么的,试探你是否... 根据我国《刑法》的规定,下列属于公共财产的是()。 苏州一级建造师报名时间是不是已经过了,要是没有赶上,今年还能有什么其 ... 盗取国家公共财产罪 我是苏州2013一级建造师考生,9月15日最后一场把身份证忘在考场了,我... 二级建造师网上报名已经通过'请问现场初审能找人代替吗我在苏州报名的... 什么是刑法中规定的公共财产,公民私人所有的财产 犯罪构成要件公私财物是什么? 西瓜幼苗刚出芽要不要浇水,要怎么管理 linux C语言编程,socket实现的即使通讯系统 西瓜苗期病害图片大全叶子发黄是怎么回事 socket编程中为什么client端的可以不用bind函数绑... 请问西瓜苗咋回事?(如图) linux socket 怎么处理大量的数据 西瓜苗长这样这是什么原因 基于Linux的远程指令系统(使用udp而不是tcp) 想要让西瓜苗长得又快又好,都有哪些小技巧呢? linux下socket编程中 bind(sockfd,(struct sockadd... 这样的西瓜苗施不施肥? linux下的bind有什么作用 西瓜苗长了这么大可以施肥吗? linux网络编程bind使用出错 西瓜幼苗,死苗是什么情况? 在Linux系统中,是否可以设置某个socket链接成功建... 大神帮我看下我的西瓜苗长得好不好,会不会结个大字瓜 怎样种西瓜苗 linux bind函数怎么释放 我的西瓜苗生病了,求西瓜种植师傅帮忙给看看,请... 西瓜苗的嫩头往上翘怎么回事 西瓜原苗和嫁接苗的区别 Linux下的c语言UDP编程 西瓜苗一般长多长 用c语言实现Linux中的pushd+n功能 linux BIND 服务以及用户权限问题. 怎样查询linux系统调用函数 linux c编写udp程序的bind报错 linux下socket编程中close()函数?? linux socket 如何发现主机是否活着 周的意思是什么? “周”字到底如何写? “周”汉语拼音怎么写? 肖邦的练习曲相对较简单的是哪首? 肖邦钢琴曲最简单 肖邦练习曲集的作品简介 肖邦名曲及名曲简介 请提供肖邦练习曲的详细资料。 我要肖邦练习曲的资料 肖邦哪首练习曲及奏鸣曲最简单?急