Linux socket编程实例:echo服务器程序

小浪SEO博客 专注SEO优化思维、SEO技术的实战分享类博客~

本文编的是echo服务器示例程序,当收到客户端的数据,服务器把数据不经加工地发送给客户,采用TCP连接,采用端口8080进行设计,在整个过程中主要涉及socket的通信。

首先建立一个 socket.代码如下:

int socketfd;

socketfd = socket(AF_INET, SOCK_STREAM, 0);

socket函数是我们写socket程序遇到的第一个函数,它在指定的协议上创建一个socket,它的函数说明如下所示:

#include

int socket ( int AddressFamily, int Type, int Protocol)

其中:AddressFamily参数指定socket操作中所要解释的网络地址类型,值为如下之一:

AF_UNIX

表示操作系统文件路径

AF_INET

表示Internet网络地址

AF_NS

表示XEROX网络地址

Type参数表明了通信的语义,即通信连接的方式。参数为如下之一:

SOCK_STREAM

提供稳定可靠的连接,并且是双向的通信方式,如TCP。

SOCK_DGRAM

提供无连接的数据报通信,如UDP。

SOCK_RAW

提供该问内部网络协议和网络接口,只有root用户才可以使用些协议。

返回值:成功则返socket描述符,出错则返回-1,可通过errno代码进行查看错误原因。

再次,把socket绑定到本机上,代码如下:

  1. structsockaddr_insa;bzero(&sa,sizeof(sa));sa.sin_family=AF_INET;sa.sin_port=htons(EHCO_PORT);sa.sin_addr.s_addr=htons(INADDR_ANY);bzero(&(sa.sin_zero),8);if(bind(socketfd,(structsockaddr*)&sa,sizeof(sa))!=0){printf("bindfailed");printf("errno=%d",errno);exit(1);}else{printf("bindsuccessfully");}

上面的代码中,定义一个scokaddr_in 结构体变量sa,然后填机服务所要开通的端口号和地址。

sa.sin_family = AF_INET;

>表明地址类型

sa.sin_port = htons(EHCO_PORT);

>端口号为8080

sa.sin_addr.s_addr = htons(INADDR_ANY);

>表明绑定在本机

然后利用bind函数,把刚才已建立的socket作为参数,绑定起来。

绑定完成后,服务器要侦听客户端的连接,因此首先要完成侦听设置这一过程,由listen函数实现,代码如下:

  1. if(listen(socketfd,MAX_CLIENT_NUM)!=0)...{printf("listenerror");exit(1);}else...{printf("listensuccessfully");}

listen(socketfd,MAX_CLIENT_NUM)表明在socketfd上侦听,其中客户个数最大值为MAX_CLIENT_NUM。

完成侦听后,可以让客户与服务器进行连接了,服务想获得客户的请求,则需要通过 accept函数来获得,同时,需要采用一个sockaddr_in结构体来获得客户的信息,代码如下:

  1. intclientfd;structsockaddr_inclientAdd;charbuff[101];socklen_tlen=sizeof(clientAdd);intclosing=0;while(closing==0&&(clientfd=accept(socketfd,
  2. (structsockaddr*)&clientAdd,&len))>0){intn;while((n=recv(clientfd,buff,100,0))>0){printf("numberofreceivebytes=%d",n);write(STDOUT_FILENO,buff,n);send(clientfd,buff,n,0);buff[n]='';if(strcmp(buff,"quit")==0){break;}elseif(strcmp(buff,"close")==0){//serverclosingclosing=1;printf("serverisclosing");break;}}close(clientfd);}

其中clientfd为客户的socket,在服务器端,每接受一个客户连接,都会返回一个客户的socket描述符,服务器根据它与客户进行通信。clientAdd为客户地址信息的结构体,在accept函数中完成对它的填充,可依此得到客户的地址信息。

  1. while(closing==0&&(clientfd=accept(socketfd,(structsockaddr*)&clientAdd,&len))>0)

等待第一个客户,当第一个客户的请求来到服务器后,该函数会返回,clientfd为客户的socket描述符。

接着进行通信

while((n = recv(clientfd,buff, 100,0 )) > 0)

等待客户的数据,收到数据后,在标准输入出显示接收的数据信息,并把它发送回给客户:send(clientfd, buff, n, 0);

在这里,我们采用简单的命令对通信进行控制,quit表示客户要结束通信过程,而 close表示客户请求关闭服务器,关闭只需使用 close函数即可完成。

下面是完整的代码:

  1. #include#include#include#include#include#defineEHCO_PORT8080#defineMAX_CLIENT_NUM10intmain(){intsocketfd;socketfd=socket(AF_INET,SOCK_STREAM,0);if(socketfd==-1){printf("errno=%d",errno);exit(1);}else{printf("socketcreatesuccessfully");}structsockaddr_insa;bzero(&sa,sizeof(sa));sa.sin_family=AF_INET;sa.sin_port=htons(EHCO_PORT);sa.sin_addr.s_addr=htons(INADDR_ANY);bzero(&(sa.sin_zero),8);if(bind(socketfd,(structsockaddr*)&sa,sizeof(sa))!=0){printf("bindfailed");printf("errno=%d",errno);exit(1);}else{printf("bindsuccessfully");}//listenif(listen(socketfd,MAX_CLIENT_NUM)!=0){printf("listenerror");exit(1);}else{printf("listensuccessfully");}intclientfd;structsockaddr_inclientAdd;charbuff[101];socklen_tlen=sizeof(clientAdd);intclosing=0;while(closing==0&&(clientfd=accept(socketfd,(structsockaddr*)&clientAdd,&len))>0){intn;while((n=recv(clientfd,buff,100,0))>0){printf("numberofreceivebytes=%d",n);write(STDOUT_FILENO,buff,n);send(clientfd,buff,n,0);buff[n]='';if(strcmp(buff,"quit")==0){break;}elseif(strcmp(buff,"close")==0){//serverclosingclosing=1;printf("serverisclosing");break;}}close(clientfd);}close(socketfd);return0;}

经过cc编译后,即可运行,在这里我们写的程序是服务器程序,要想完成通信,也得写一个客户端程吧???

呵呵,我们先把客户端的程序放下来,先测测我们服务器程序吧,在这里,我们使用 telnet充当客户端进行测试,telnet可以说是一个很好的客户端程序,呵呵:

本机IP为192.168.0.69,整个通信过程如下:

  1. linyongting@linyongting:~$telnet192.168.0.698080Trying192.168.0.69...Connectedto192.168.0.69.Escapecharacteris'^]'.hello!Thisismyfirstpacket.Canyoureplytome?hello!Thisismyfirstpacket.Canyoureplytome?Ohh,Udidit!Ohh,Udidit!seeUnexttime!!!seeUnexttime!!!quitquitConnectionclosedbyforeignhost.linyongting@linyongting:~$telnet192.168.0.698080Trying192.168.0.69...Connectedto192.168.0.69.Escapecharacteris'^]'.closecloseConnectionclosedbyforeignhost.

上面连接了两次,第一次时,与服务器通信3次,每次发信息过去后,都收到与发出来一模一样的信息。当用户输入quit的时候,服务端就会关闲与客户通信的socket,通信结束。第二次客户只输入close,服务器响应后马上关闭服务器,同时也关闭客户端。下面是服务器的显示内容:

  1. linyongting@linyongting:~/program/c$./echoServersocketcreatesuccessfullybindsuccessfullylistensuccessfully//第一次通信numberofreceivebytes=53hello!Thisismyfirstpacket.Canyoureplytome?numberofreceivebytes=16Ohh,Udidit!numberofreceivebytes=20seeUnexttime!!!numberofreceivebytes=6quit//第二次通信numberofreceivebytes=7closeserverisclosing

当客户端输入quit时,只是客户端关闭,服务器还接着为其它客服端服务。当客户端输入 close时,服务关闭。

当前出现的问题:

我们的服务器序程只能与一个客户端进行通信,只能当客户端发出quit命令关闭后才能与下一个客户端通信。

相关广告
  • Linux socket编程实例:echo服务器程序 Linux socket编程实例:echo服务器程序 Linux socket编程实例:echo服务器程序
相关阅读

Linux socket编程实例:echo服务器程序

2019/10/10 17:48:23 | 谷歌SEO算法 | SEO优化