评价socket C/S端结构

comman_wang 2006-04-17 09:24:13
在得到许多朋友的指点之后,我构造了一个socket的客户端和服务器端的设计方案,请大家评价一下是否合理,谢谢!

由于客户端和服务器端存在多次交互,在设计采用一次连接,多次使用(通知相关子进程进行发送和接收)的方法,主观上认为可能比每次都fork一个子进程的效率要高一些。不知认识是否正确?

相关异常处理还没有详细考虑。

客户端结构:

main()

初始化管道环境;

while(1)

if(数据准备好)

if(相应的发送子进程(或线程)已初始化)

往相应的发送管道写入数据;
激活通知(通知子进程从相应管道里读数据);//***?是否利用管道阻塞也可以实现

else

初始化发送子进程(或线程),包括socket连接;
fork子进程;
if(子进程)

while(1)

等待主进程通知;
从相应的发送管道读取数据,发送给Server;


}//(end of else)
}//(end of 数据准备好)
}//(end of while(1))



服务器端结构:

main()

初始化socket环境;

while(1)

if(监听socket accept客户端连接成功)

if(相应节点[client]的接收子进程(或线程)已初始化)

关闭该节点的接收子进程(或线程);


fork子进程;
if(子进程)

while(1)

等待该socket有数据可读(select实现);
接收数据并进行相关处理;



}//(end of 监听成功)
}//(end of while(1))
...全文
308 11 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
YanDong_8212 2006-04-17
  • 打赏
  • 举报
回复
我提出两点疑问:
1.客户端为什么还要fork子进程呢?客户端应该可以在一个进程里面收发数据。
2.子进程都是while(1),要考虑下如何终止这个进程。

我建议客户端这样设计:
main()

初始化管道环境;
condtion = 1;
while(condition)//conditon可以是从服务器端收到的某个数据,让服务器来关闭此socket.

if(数据准备好)

if(当前socket不可用)
{
初始化socket连接;
}//(end of if)

发送请求桢;
接收返回桢;
解析数据,并按协议执行相应工作,其中存在一种修改condition的协议;
}//(end of 数据准备好)
}//(end of while(1))
close(socket);
alaiyeshi 2006-04-17
  • 打赏
  • 举报
回复
恩,这样的环境
客户端也要保留信息么?
那什么时候结束呢?
这样,一旦遇到了异常,那你的连接不就会出现僵尸进程么?
linux_DD 2006-04-17
  • 打赏
  • 举报
回复
学习
comman_wang 2006-04-17
  • 打赏
  • 举报
回复
这个方案主要针对于局域网内多个节点间的数据交互,规模一般不会超过50个节点。
节点初始化一次后两端都保留该连接的相关信息,以后这两个节点交互时就使用这个连接(不再初始化了),应该不会浪费时间吧(我这样设计就是想节省初始化和结束的时间)。

欢迎继续讨论,谢谢!
alaiyeshi 2006-04-17
  • 打赏
  • 举报
回复
我觉的用进程池这个模型,可能在重负载的时候,表现会好一些
你现在的这个,当遇到大量请求的时候,要做大量的初始化工作,如果工作量小,那么大量的时间就浪费在初始化和结束上了

个人看法,很是偏颇
YanDong_8212 2006-04-17
  • 打赏
  • 举报
回复
其实我想推荐一本《用TCP/IP协议进行网际互联》,这本讲得很系统,我都买了的chinapub上可以买到。
tonyMCM 2006-04-17
  • 打赏
  • 举报
回复
《LINUX网络编程》对楼主应该有用

提醒楼主 处理僵尸进程要注意

另外发送接受的时候 多做一些保护(出错信息的输出),有助于找问题

YanDong_8212 2006-04-17
  • 打赏
  • 举报
回复
那样的话就没什么问题。

unix的事件一般用信号来处理:
首先,每个信号都有一个名字。这些名字都以三个字符S I G开头。例如,S I G A B RT是夭折
信号,当进程调用a b o r t函数时产生这种信号。S I G A L R M是闹钟信号,当由a l a r m函数设置的时
间已经超过后产生此信号。V 7有1 5种不同的信号, S V R 4和4 . 3 + B S D均有3 1种不同的信号。
在头文件< s i g n a l . h >中,这些信号都被定义为正整数(信号编号)。没有一个信号其编号为
0。在1 0 . 9节中将会看到k i l l函数,对信号编号0有特殊的应用。P O S I X . 1将此种信号编号值称为
空信号。
很多条件可以产生一个信号。
• 当用户按某些终端键时,产生信号。在终端上按D E L E T E键通常产生中断信号(S I G I N T)。
这是停止一个已失去控制程序的方法。(第11章将说明此信号可被映射为终端上的任一字符。)
• 硬件异常产生信号:除数为0、无效的存储访问等等。这些条件通常由硬件检测到,并将
其通知内核。然后内核为该条件发生时正在运行的进程产生适当的信号。例如,对执行一个无
效存储访问的进程产生一个S I G S E G V。
• 进程用k i l l ( 2 )函数可将信号发送给另一个进程或进程组。自然,有些限制:接收信号进程
和发送信号进程的所有者必须相同,或发送信号进程的所有者必须是超级用户。
• 用户可用k i l l ( 1 )命令将信号发送给其他进程。此程序是k i l l函数的界面。常用此命令终止
一个失控的后台进程。
• 当检测到某种软件条件已经发生,并将其通知有关进程时也产生信号。这里并不是指硬
件产生条件(如被0除),而是软件条件。例如S I G U R G (在网络连接上传来非规定波特率的数
据)、S I G P I P E (在管道的读进程已终止后一个进程写此管道),以及S I G A L R M (进程所设置的闹
钟时间已经超时)。
信号是异步事件的经典实例。产生信号的事件对进程而言是随机出现的。进程不能只是测
试一个变量(例如e r r n o )来判别是否发生了一个信号,而是必须告诉内核“在此信号发生时,请执行下列操作”。
可以要求系统在某个信号出现时按照下列三种方式中的一种进行操作。
(1) 忽略此信号。大多数信号都可使用这种方式进行处理,但有两种信号却决不能被忽略。
它们是:S I G K I L L和S I G S TO P。这两种信号不能被忽略的原因是:它们向超级用户提供一种使
进程终止或停止的可靠方法。另外,如果忽略某些由硬件异常产生的信号(例如非法存储访问
或除以0),则进程的行为是未定义的。
(2) 捕捉信号。为了做到这一点要通知内核在某种信号发生时,调用一个用户函数。在用
户函数中,可执行用户希望对这种事件进行的处理。例如,若编写一个命令解释器,当用户用
键盘产生中断信号时,很可能希望返回到程序的主循环,终止系统正在为该用户执行的命令。
如果捕捉到S I G C H L D信号,则表示子进程已经终止,所以此信号的捕捉函数可以调用w a i t p i d
以取得该子进程的进程I D以及它的终止状态。又例如,如果进程创建了临时文件,那么可能要
为S I G T E R M信号编写一个信号捕捉函数以清除临时文件( k i l l命令传送的系统默认信号是终止
信号)。
(3) 执行系统默认动作。
以上是基本概念,根据你的要求,你可以自定义信号SIGUSR信号,然后调用你的函数。
具体请参考《UNIX环境高级编程》。
comman_wang 2006-04-17
  • 打赏
  • 举报
回复
to YanDong_8212(谢科):
对于通知我是这样考虑的(不知是否合适,请指教):
1、客户端的子进程因为是循环利用,需要等待主进程通知(当主进程需要和服务器再次进行数据交互时,就往相应的管道里写入数据,并激活事件通知子进程发送数据);
2、服务器端的子进程我想采用select阻塞,直到有数据可读才接收;

另外在unix下事件如何定义实现?(刚从windows转过来)

谢谢!

YanDong_8212 2006-04-17
  • 打赏
  • 举报
回复
那样的话,你的结构就行。
但还有个问题:

等待主进程通知;
等待该socket有数据可读(select实现);

都是被动的等待,应该设计成有一方是事件的发起方:)
comman_wang 2006-04-17
  • 打赏
  • 举报
回复
to alaiyeshi(七宝树八宝饭) :
客户端也需要保留的,下次跟服务器交互仍采用这个连接。客户端主进程退出时才关闭这个连接。如果在工作过程中出现异常(不管是客户端还是服务器端),关闭这个连接,并清空该端保留的信息变量,同时子进程退出;对端也可以感知这个关闭信息(通过接收失败清空变量)。

to YanDong_8212(谢科):
1、客户端fork子进程的做法主要是因为其可能需要同多个server进行数据交互,为了让其相互间互不干扰,故采用fork子进程的方法;
2、建议很正确,子进程中while(1)应该考虑退出循环。在实际应用中采用了类似你建议的方法,在while(1)循环中增加判断退出标志激活,如果激活,就跳出循环,退出该子进程。在服务器端的子进程中也采用此种方法退出循环。

23,217

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧