天天看点

socket编程的常见问题

  • 英文小册原文地址:​​beej.us/guide/bgnet…​​
  • 作者:Beej
  • 中文翻译地址:​​www.chanmufeng.com/posts/netwo…​​

1. 我从哪获取这些头文件资料?

如果你的系统中没有自带这些文件,或许你根本就不需要他们。你得看一下你平台的使用手册。

对了,如果你是为Windows开发程序,你只需要​

​#include <winsock.h>​

​。

2. bind()报“Address already in use”异常怎么办?

你必须对正在监听的socket使用​

​setsockopt()​

​​函数,并设置 ​

​SO_REUSEADDR​

​​ 选项。看一下​

​bind()​

​​章节和​

​select()​

​章节中的例子,你就明白了。

3. 我该如何获取到系统中已经打开的socket列表?

使用​

​netstat​

​命令。使用细节你需要参考man手册,不过你只要输入下列指令就能获取到一些不错的信息:

$ netstat      

4. 我该如何查看路由表(routing table)?

执行​

​route​

​​命令(多数的Linux系统是在​

​/sbin​

​​下),或者​

​netstat -r​

​指令。

5. 如果我只有一台电脑,我该怎么运行Client/Server程序?我需要连接外网吗?

幸运的事,所有系统都有一个回环(loopback)虚拟网络“设备”,这个设备位于内核中,并假装自己是个网卡(这家伙就是​

​ifconfig​

​​中列出的“​

​lo​

​”)。

假设你登陆一台名为“goat”的设备,并在一个窗口中运行了Client程序,在另一个窗口中运行了Server端程序。或者你也可以在后台运行Server程序(用​

​server &​

​),在另一个窗口中运行Client程序。

​loopback设备​

​​的用处就是,你可以使用 ​

​client goat​

​​ 或者 ​

​client localhost​

​​ (因为“​

​localhost​

​​”已经在你的​

​/etc/hosts​

​中定义好了),这样你就可以让client在没有网络的情况下也可以与server通信。

简而言之,不需要改变任何代码,就可以让你的程序在没有网络的单机上运行!

6. 如果远程断开了连接,我该怎么知道呢?

你可以分辨,因为​

​recv()​

​​会返回​

​0​

​。

7. 我自己怎么实现“ping”这个小工具?啥是ICMP?我从哪儿能学到更多关于raw scoket和SOCK_RAW的知识?

你对​

​raw socket​

​​的全部疑问都可以在 ​​W. Richard Stevens’ UNIX Network Programming books​​这本书中找到答案。在Stevens’ UNIX Network Programming源代码的​

​ping​

​子目录中,你可以找到​​ping的源码​​。

8. 我该如何改变或缩短调用connect()的过期时间?

这个问题 W. Richard Stevens 已经回答了,我们就不狗尾续貂了。你可以参考UNIX Network Programming源代码中的 ​​lib/connect_nonb.c​​。

其要点是,使用​

​socket()​

​​创建一个socket descriptor,将其设置为​

​non-blocking​

​​,调用​

​connect()​

​​,如果一切顺利,​

​connect()​

​​将立即返回​

​-1​

​​,​

​errno​

​​将设置为​

​EINPROGRESS​

​​。然后,你可以调用​

​select()​

​​,并在​

​read​

​​和​

​write​

​​集合中传递socket descriptor。如果没有超时,则表示​

​connect()​

​​调用已完成。此时,你必须使用​

​getsockopt()​

​​设置​

​SO_ERROR​

​​选项,以获取​

​connect()​

​​调用的返回值,如果没有错误,该值应该为​

​0​

​。

最后,在你开始通过socket传输数据之前,你可能姜再将其设置为​

​blocking​

​。

这样做有一个好处,就是让你的程序在​

​connecting​

​​(连接期间)也可以做别的事情。比如:你可以将​

​timeout​

​​设置为500ms,并在每次​

​timeout​

​​时更新屏幕上的提示信息,然后再次调用​

​select()​

​​。当你调用​

​select()​

​并超时(例如,达到20次)时,你就知道是时候放弃这个连接了。

强烈建议你看看Stevens的源码,找个好例子研究一下。

9. 我该怎么写Windows网络程序?

首先,卸载Windows,然后装一个Linux或者BSD。。。。哈哈哈哈,开个玩笑。

继续阅读