很久没有更博客了,这几天还在做学校的计网实验,做的我真的头大,实验是一个多人聊天室,不限制语言但是要求使用socket。为了满足自己一点私欲,于是想在服务器上用C写个多线程的服务器,然后本地尝试用Java与他通信。
经过亲身实践,在这里奉劝各位,不要这么做,除非你不得不调用一个老版本的C服务端,不然还是统一语言和api比较好,虽然socket它本质是一个东西,但是不同语言对外的socket调用方式也会变化,这可是一个大坑。
废话多了点,下面就展示让我这几天头大的罪恶源头。
这个事情起源于一段神奇的代码
很简单的代码,在前面开始监听某个端口后,程序就阻塞接收某个客户端扔过来的socket请求,然后通过handle函数来处理那个发送的数据(其实就是读取后输出到终端上),最后再返回一段字符串。
一切似乎都很完美,但是这个程序实际上是个短连接,每读一次数据并且写一次数据以后就会把客户端的套接字销毁,然后在循环的开始重新开始等待下一次的连接。 那可太麻烦了,我心目中理想的程序不应如此,于是我试图写一个长连接式的程序。
可是要怎么做呢,我想到用多线程,每一个线程维护一个客户端套接字,然后主函数专门用来阻塞监听新的客户端套接字,这岂不是完美,于是我动手大胆更改了程序。 谁能想到这是罪恶的根源!!!
它就卡在这里不动了,仔细看看程序,它应该是在send的时候卡住了。。 于是ctrl+c向程序发送了一个SIGINT信号强制把他中断了,这时候神奇的事情发生了。。 客户端居然收到了消息!! 可是这个时候服务程序应该已经结束了,难道是说它是在程序结束的时候发送的吗? 我一头雾水,于是想到用gdb来给他调试调教一番。 在send前面加入断点 执行单步调试 然后发现它运行到一半开始跑thread相关的代码了,(其实我到现在还没有搞懂为甚么会转到这里,我想可能是时间片的时间到了然后内核开始想要把线程挂起,但是由于send是阻塞运行的,所以没能把它结束吗?)在互联网上一番畅游,我了解到线程取消点的概念,原来send,recv,read,write都是取消点函数(关于这个概念大家可以自行搜索,我到现在其实还没有特别搞懂)。于是菜鸡的我开始试图以这个为出发点解决问题。。
然而并没有什么卵用!!!
就在我一边感叹自己之菜一边开始考虑给服务器装java环境的时候,最开始短连接的代码突然给了我提示。。 难道要等到把套接字关了才能把字节发出去嘛?
于是默默的改了改,居然成功了。。 这是为什么呢?激动之余我就写了这篇博,现在想想可能是不同平台不同接口的问题,代码可真是个神奇的东西。
但是这也意味着没办法写长连接的程序了,我不得不面临计网实验低分飘过的现实。
———————————————————————————————— 结尾再唠叨唠叨吧,虽然我一直说要定时更新博文,但是写这个真的好麻烦,加上自己那么菜,大多数时候都不敢写啊。。讲道理这篇博好像都算不上技术博客了吧。。
接下来一年还是在做小车,压力真的好大呀,像现在正是开始准备做车的时候我却花了那么多时间来做实验我真的于心不忍,但不管怎么样还是要好好努力呀,这一年可千万不能拖车队的后腿。
