完整word版linux环境下c语言书写socket服务器程序的步骤和注意事项_第1页
完整word版linux环境下c语言书写socket服务器程序的步骤和注意事项_第2页
完整word版linux环境下c语言书写socket服务器程序的步骤和注意事项_第3页
完整word版linux环境下c语言书写socket服务器程序的步骤和注意事项_第4页
完整word版linux环境下c语言书写socket服务器程序的步骤和注意事项_第5页
已阅读5页,还剩14页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、在linux卜用c语言编写socket fK务器。ft先分析需要解决的问题:1. Socket的处理机制。一般的处理方法是在服务端socket初始化和建立监听之后,开C一个while死循环。不 断接受传递过來的socket链接请求,如果链接请求成功,开启1个子进程fork.在子进 程中对socket进行处理。处理完毕之后,子进程结束退出。经本人测试研究发现了1中框架的几个问题,比段的突出。具体如K2. 开启了进程容易产生僵厂进e。一开始的代码不完善,在子进程中exit后,父进程没冇对其进行操作,导致了子进程成 为僵尸进程,处理此问题有3种方法,将在后面进行详细说明。3- Socket的处理容易

2、不严谨,导致程序奔溃。Socket的处理要严谨,否则在程序的运行过程中会出现socket资源不能释放的问题。4. 口志文件的处理。在多进程(线程)处理中会面临一个日志文件不可共享写的问题。398810897。本文中的代码均为作者测试使用过,在本文的敲后会附上所右代码,如仃疑问或苕需要町以 联系作者,qq:几体问题分析:1. socket的基本框架(代码文件为server01.c)c在windows和linux卞的socket编程基本上是一样的,没右多大的差别,都是遵循 着 创建socket、定义socket (socket IK值)、绑定socket、开启监听、socket收发、关 R1 so

3、cket的流程来的,在windows b一开始还需要初始化socket版木,在这里主要针 对的linux坏境卜的socket-所以windows卜的东西就不细说了。创建可以收发数据的socket的必须的步骤如下:创建 socket sock=socket(AF_INEISOCK_STREAM,0); if(sock0)printfCsocket error n”); return 0;printfC*sock-ret=%dn*sock);网络字节序server.sin_family=AF_INET;serversin addrs addr=INADDR ANY;servers!n.port=h

4、tons(bOOO);/MYPOKIbzero (&(server,sin_zero),8);setsockopt(sock,SOL_SOCKET char*)&bReuseaddcsizeof(int);/bind if(ret=bind(sock4struct sockaddr)0)/*bind()5OREUSEADDR,(constsockaddr*)&serveGsizeof(structprintfCbind errorn); return 0;printf(bind-ret=%dnjet); ret=-9;if(ret=listen(sock,100)0)/* * * *liste

5、n()printfClisten errorn); return 0;printf(listen*ret=(%dnret);在socket的创建以及初始化之后,做一个while (1)的死循坏进行和客户端的链接 while(l)namelen=sizeof(struct sockaddr Jn);/sockaddrJn:feht 信息 if(msgsock=acce pt(sock(struct)&client&namelen)=(n=recv(sockettemp,data_butMAXLINE,0)continue;elsesend(sockettemp,ch_send_backstrle

6、n(ch_send_back),0);close(sockett emp);break;n3;close(sockettem p); printfCSOCKET END exit(O);以上就足一个简单的socket服务器e序的框架了。2.僵尸进程的处理。在程序运行之后,会出现如下的问题,就是fork 了子进程之后,父进程便不再处 理子进程,导致了僵尸进程的出现。如卜图所示,会出现一个serverOl 的僵尸进程: rootSlocalhost PS -fe Igxep servergdmer ver00:30:COZu3r/libxec/bonobo-activation-root16837

7、I8330 08:27oaroot21883217910 11:40?root22532217950 12:45PC3/2root22533225320 L2:46PC3Z2root22630226090 12:55PC3Z3244710 SepQS ?&c-accivaze icr-output-f(1-1200:30:0000:30:0000:DO:CO 00:30:00 00:30:00/usr/libfixec/opfinssli/s ftp-serve /U3x/libxec/open33h/3ftp-3exve ./servetOLserveiOl grep server现疔四种方

8、式町以处理.为了避免这个问题的出现,(1)父进程通过wait和waitpid等两数等待子进程结束,这会导致父进程挂起。执行wait()或waitpidO系统调用,则子进程在终止后会立即把它在进程表中的数据 返回给父进程,此时系统会立即删除该进入点。在这种情形下就不会产生defunct进程。(2)如果父进程很忙,那么町以用signal函数为SIGCHLD安装handler。在子进程结 束后,父进程会收到该信号,可以在handlerP调用wait回收。(3)如果父进程不关心子进程什么时候结束,那么可以用signaKSIGCLD, SIGJGN)或 signal(SIGCHLD,SIGGN)通知内核

9、,自己对子进程的结束不感兴趣,那么子进程结束后, 内核会回收,并不再给父进e发送信号fork两次,父进程fork-个子进程,然后继续工作,子进程fork-个孙进程后 退出,那么孙进程被init接管,孙进程结束后,init会回收。不过子进程的回收还要自 己做。具体的测试结果:(1) 方法是町以避免僵r进程的产生,但是效率很低,毎一次fork 了子进程,父进程 都要等到子进程exit T才能继续运行,不适合在并发量很高的服务器程序上使用。(2) 在程序中定义一个 signal 的函数 void proc_child(int SIGNO);然后在server监听了之后,和客户端链接之前,调用此函数s

10、ignal(SIGCHLD, Proc_child);函数的具体实现如K:void Proc_child(int SIGNO)int pid = -1;int stat;pid = waitpid(l, &stat, WNOHANG);具体代码参考serverO2.Ca试验结果还是比较满意,在单客户端访问时,效率几乎没什么影响,也不会产生僵 厂进程,但是多个客户端,或者长期人量的链接的时候还是会产生尸进程。测试 环境比较难以搭建.(3) 方法町以,而II简单容易实现,具体代码参考serverOS.Co(4) 没冇测试,所以这里就只好不说了。3. 在测试的过程中发现了由于作者一开始对socket

11、没有释放导致程序不能收发数据的现 象。主婆是在accept Z后,跳出了 fork之后没有close造成的。4. 口志文件是一个比较麻烦的问题。一般情况下,口志要写到一起,只能一个一个的进程对文件进行操作,必然影响程序的 并发性。这种情况下就需要建立一个缓冲区,将【I志的数据保存到缓冲区中,然后在定 时刷新,将缓冲区中的数据写到口志里面去。在windows b作者比较喜欢使用一个动态链接库建立缓冲区的方法来实现,而在linux 作者使用了一个比较简单的pipe (管道)的方法来实现这个。、具体的代码见server04.附录-代码ServerOl:/#inelude include #inclu

12、de include #include include #include include #inelude include #inelude #define MAXLINE 4096int main()int sock;/server socketstruct sockaddrjn server;/server socketaddrjn struct sockaddr_in die nt;char msgsock;/client socketint namelen;/socket addr lengthint bReuseaddr=l;int ret=*9;int clientJd=0;创建

13、socket sock=socket(AF_INETSOCK_STREAM,0); if(sock0)printfCsocket errorn); retur n 0;printf(sock-ret=%dnsock);网络字节序 server.sin_family=AHJNtl; serversin addrs addr=INADDR ANY;server,sin_port=htons(6000);/MYPORTbzero(&(serversin_zero)8);setsockopt(sock,SOL_SOCKET5O_REUSEADDR4const char*)&bReuseaddr;si2

14、eof(int);/bindif(ret=bind(sock,(struct sockaddr )&server,sizeof(struct sockaddr)0)/* * * * bind()phntf(bind errorn); retur n 0;printf(bind-ret=%dnret); ret=-9;if(ret=listen(sock400)0)/*listen()printfClisten errorn*); return 0;printf(listen-ret=%dn,ret);while(l)n amelen=sizeof(struct sockaddrn);/sock

15、addrn:地址佶息 if(msgsock=acce pt(sock(struct sockaddr拿)&client&namelen)=(n=recv(sockettemp,clata_butMAXLINE,0)continue;elsesend(sockettem p,ch_send_back,strlen(ch_send_back)/); close(sockettem p);break;close(sockett emp); printf(SOCKET END exit(O);else/fatherclose(msgsock);usleep(lO);return 0;ServerO2:

16、/* */#include include #inelude include include include ftinelude include vnetinet/in,h include include # include define MAXLINE 4096 void proc_child(int SIGNO) int pid = -1;int stat;pid = waitpidd &stal WNOHANG);int main()int sock;/server socketstruct sockaddr_in server;/server socketaddrjn struct s

17、ockaddr_in die nt;char msgsock;/client socketint namelen;/socket addr lengthint bReuseadclr=l;int ret=9;int client id=0;创建 socket sock=socket(AF_INET,SOCK_STREAM,0); if(sock0)printf(*socket errorrT); return 0;printf(sock-ret=%dn,sock);网络字节序serversin_family=AF_INET;server.sin_addrs_addr=INADDR_ANY;se

18、rver,sin_port=htons(6000);/MYPORTbzero(&(serversin_zero)8);setsockopt(sock,SOL_SOCKET,SO_REUSEADDR4const char*)&bReuseadclr;si2eof(int);/bindif(ret=bind(sock,(struct sockaddr )&servecsizeof(struct sockaddr)0)/*bind()printfCbind errorn); retur n 0;printf(*bind-ret=%dn,ret); ret=-9;if(ret=listen(sock4

19、00)0)/*listen()printfClisten errorn*); return 0;printf(*listen-ret=%dn,ret);signal(SIGCHLD, proc.child);/signal(SIGCHLD, SIGJGN);while(l)n amelen=sizeof(struct sockaddrjn);/sockaddrjn:地址(3 息 if(msgsock=accept(sock(struct sockaddr*)&client,&namelen)=(n=recv(sockettemp,data_butMAXLINE,0)continue;elses

20、end(sockettem p,ch_send_backstrlen(ch_send_back)X); close(sockettem p);break;rr);close(sockettem p); printfCSOCKET END exit(O);else/fatherclose(msgsock);usleep(lO);return 0;void proc_child(int SI6N0)int pid = -1;int stat;pid = waitpid(-l, &stat, WNOHANG);Server03:/* /include include include #inelude

21、 #include #inelude include #include include ftinelude include #define MAXLINE 4096 void proC-Child(int SIGNO) int pid = -1;int stat;pid = waitpid(-l, &stat, WNOHANG);int main() int sock;/server socketstruct sockaddr_in server;/server socketaddrjn struct sockaddrjn client;char msgsock;/client socketi

22、nt namelen;/socket addr lengthint bReuseaddr=l;int ret=-9;int clientJd=0;创建 socket sock=socket(AF_INETSOCK_STREAM,0); if(sock0)printf(socket errorn); retur n 0;printf(*sock-ret=%d)n3ock);网络字节序server.sin_family=AFJNET;serversin addrs addr=INADDR ANY;server.sin_port=htons(60CX);/MYPORTbzero(&(serversi

23、n_zero)#8);setsockopt(scx:k,SOL_SOCKET,SO_REUSEADDR4 const char*)&bReuseaddr,sizeof(int);/bindif(ret=bind(sock,(struct sockaddr *)&server,sizeof(struct sockaclclr)0)/*bind()printfCbind errorn); return 0;printf(*bind-ret=%dnret);ret=-9;if(ret=listen(sock400)0)/*listen()printfClisten errorn*); retur n

24、 0;printf(*listen-ret=%dn,ret);/ signal(SIGCHLD, proc_child); signal(SIGCHLD, SIGJGN);while(l)namelen=sizeof(struct sockaddrjn);/sockacldrjn:地址信息 if(msgsock=acce pt(sock,(struct sockaddr)&client,&namelen)=(n=recv(sockettemp,data_butMAXLINE,0)conti nue;elsesen d(sockettemp,ch_se nd_backstrle n(ch-Sen

25、d_back),O);close(sockettem p);break;W);closefsockettem p); phntf(*SOCKETEND exit(O);else/fatherclose(msgsock);usleep(lO);return 0;void proc_child(int SIGNO)intp id = -1;int stat;pid = waitpid(-l, &$tat, WNOHANG);Server04/*/#inelude include #inelude #include #inelude include #inelude # include #inelu

26、de include include ffdefine MAXLINt409b include logfile,hvoid proc_child(int SIGNO);int main()Int sock;/server socketstruct sockaddrjn server;/server socketaddrjn struct sockaddr.in client;char msgsock;/client socket int namelen;/socket addr length int bReuseaddr=l;int ret=-9;int client_id=O;FILE *

27、pFile;/ 志句柄 intpipe_fd2;/ 管道 char chJog(lOOO);开应口志进程,打开口志文件.打开管道P File=SetFileHandle();if(pipe(pipe_fd)0)printfCpipe create errorrT); return -1;while(l)WriteLog(pipe_fd0,NULUpFile; usleep(100);/100ms 刷新一次口志else/WritePipe(pipe_fcll/*LOG-LOGlog process begin?);打开设备创建 socket sock=socket(AF_INETSOCK_STR

28、EAM,0); if(sockvU) printf(*socket errorn*); sprintf(chJog/(SOCK socket create Error!); /WritePipe(pipe_fdl,chJog);retur n 0;printf(sock-ret=%dnsock);sprintf(chJog/SOCK socket create OKsocket=%d!sock); /WritePipe(pipe_fdl,chJog);网络字节序server.sin_family=AFJNET;serversin addrs addr=INADDR ANY;server,sin

29、_port=htons(6000);/MYPORTbzero (&(serve 匚 sin_zero),8);setsockopt(sock,SOL_SOCKET,SO_REUSEADDR4co nst char*)&bReuseaddi;sizeof(int); /bindif(ret=bind(sock,(struct sockaddr )&server,sizeoffstruct sockaddr)0)/*bind()printf(bind errorn); sphntf(ch_log/SOCK socket bind Error!); /WritePipe(pipe_fdl,chJog

30、);return 0;sprintf(chJog/SOCK socket bind Ok!);/WritePipe(pipe_fdl,chJog); printf(bind-ret=%dn/et); ret=-9;if(ret=listen(sock400)0)/*listen()printf(listen errorn*);sprintf(chog门SOCK socket listen ErrorP); /WritePipe(pipe_fdl,chJog);return 0;printf(*listenret=%dnret); sprintf(chJog/*(SOCK socket list

31、en Ok!);/WritePipe(pipe_fdl,chJog);/signal(SIGCHLD, proc_child); signal(SIGCHLD, SIGJGN);while(l) p rintfCacce pt errorn);n amelen=sizeof( struct sockaddrjn);/sockaddrjn:地址信息 if(msgsock=acce pt(soch(struct sockaddr)&client,&namelen)=(n=recv(sockettem p,data-butMAXLINE#O)con tinue;elsesprintf(chJog/S

32、OCK recv data from sock=%d,data=%ssockettemp,data_buf);/WritePipe(pipe_fdl,chJog);/WritePipe(pipe_fdlKchJog);sen d(sockettemp,ch_se nd_backstrle n(ch-Send_back)/); sprintf(chJog/SOCK socket sendbackdata=%s;ch_send_back);/WritePipe(pipe_fdl,chJog); close(sockettemp);break;n1;close(sockettem p); printfCSOCKET END exit(O);else/fatherclose(m

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论