Unix网络编程—为客户端进程指定端口
2016-05-02 16:01
459 查看
了解Unix/Linux的人都知道,一般而言,只会在服务器端的监听进程才会指定端口,那么客户端的进程是否也能够指定端口呢?
我们同样利用bind函数来为客户端的进程指定端口。
首先,我们运行一个不指定端口的客户端程序,看一下数据包传输的情况:
1.通过sudo tcpdump命令打开工具软件
2.执行客户端程序
3.观察数据包传输的情况
结果如下:
关于数据包的内容我就不解释了,我们只要知道,master是客户端,39400是客户端进程的端口,下面重复一次上面的操作,结果如下:
我们发现,前后两次执行的客户端进程所用的端口不一样了,虽然说端口由操作系统来指定,可是为什么要换一个呢?
我们通过netstat -an命令来查看端口状态,如下图:
可以看到,当执行完客户端程序后的一段时间内(TCP连接还没完全关闭),连接处于TIME_WAIT(这个时间实际上是2MSL),也就是说在这段时间内,该端口还不能被其他进程所使用,所以操作系统为了避免这种情况,会选择一个不同的端口号分配给进程。
下面来说一下客户端进程指定端口号:
其实很简单,跟服务器端一样,我们通过调用bind函数来绑定端口号,我在自己的实验代码中加入了一下的语句:
struct sockaddr_in clientaddr;
memset( &clientaddr, 0, sizeof( clientaddr ));
clientaddr.sin_port = htons( 8000 );
bind( sockfd, ( struct sockaddr * )&clientaddr, sizeof( clientaddr )); //sockfd是socket函数的返回值
编译运行,仍然通过sudo tcpdump来查看数据包传输情况,如下图:
我们发现,客户端的端口果然改变了,是不是到此就成功了呢?我们执行完第一次client程序后,立刻执行第二次client程序,结果如下:
我们很神奇的发现,端口号并非是我们所指定的!
那么为什么第一次执行用的是我们指定的端口号,第二次就不是了呢,这就是因为我们上面提到过的TIME_WAIT这个状态造成的。我们通过查看端口状态,的确可以看到8000处于TIME_WAIT状态,所以它不能被分配给第二次执行的进程。只要等第一次执行完毕以后,等待端口恢复正常以后,再执行第二次,就可以看到我们想要的结果。
这里我对Linux的端口选择机制不是很了解,大胆推测一下,如果操作系统发现指定的端口不可用,那么就会任意分配一个给进程,不会产生任何错误报告(即使有,对程序员来说也是透明的)。
我们同样利用bind函数来为客户端的进程指定端口。
首先,我们运行一个不指定端口的客户端程序,看一下数据包传输的情况:
1.通过sudo tcpdump命令打开工具软件
2.执行客户端程序
3.观察数据包传输的情况
结果如下:
关于数据包的内容我就不解释了,我们只要知道,master是客户端,39400是客户端进程的端口,下面重复一次上面的操作,结果如下:
我们发现,前后两次执行的客户端进程所用的端口不一样了,虽然说端口由操作系统来指定,可是为什么要换一个呢?
我们通过netstat -an命令来查看端口状态,如下图:
可以看到,当执行完客户端程序后的一段时间内(TCP连接还没完全关闭),连接处于TIME_WAIT(这个时间实际上是2MSL),也就是说在这段时间内,该端口还不能被其他进程所使用,所以操作系统为了避免这种情况,会选择一个不同的端口号分配给进程。
下面来说一下客户端进程指定端口号:
其实很简单,跟服务器端一样,我们通过调用bind函数来绑定端口号,我在自己的实验代码中加入了一下的语句:
struct sockaddr_in clientaddr;
memset( &clientaddr, 0, sizeof( clientaddr ));
clientaddr.sin_port = htons( 8000 );
bind( sockfd, ( struct sockaddr * )&clientaddr, sizeof( clientaddr )); //sockfd是socket函数的返回值
编译运行,仍然通过sudo tcpdump来查看数据包传输情况,如下图:
我们发现,客户端的端口果然改变了,是不是到此就成功了呢?我们执行完第一次client程序后,立刻执行第二次client程序,结果如下:
我们很神奇的发现,端口号并非是我们所指定的!
那么为什么第一次执行用的是我们指定的端口号,第二次就不是了呢,这就是因为我们上面提到过的TIME_WAIT这个状态造成的。我们通过查看端口状态,的确可以看到8000处于TIME_WAIT状态,所以它不能被分配给第二次执行的进程。只要等第一次执行完毕以后,等待端口恢复正常以后,再执行第二次,就可以看到我们想要的结果。
这里我对Linux的端口选择机制不是很了解,大胆推测一下,如果操作系统发现指定的端口不可用,那么就会任意分配一个给进程,不会产生任何错误报告(即使有,对程序员来说也是透明的)。
相关文章推荐
- Lua下基本的网络编程示例
- linux网络编程用到的网络函数详解用和使用示例
- C#网络编程基础之进程和线程详解
- C++ 网络编程 总结
- Linux网络编程之UDP Socket程序示例
- Android网络编程之UDP通信模型实例
- 谈谈新手如何学习PHP网络编程第1/2页
- Python 网络编程起步(Socket发送消息)
- java必学必会之网络编程
- c# socket网络编程接收发送数据示例代码
- NodeJS学习笔记之网络编程
- Java网络编程之简单的服务端客户端应用实例
- java网络编程之识别示例 获取主机网络接口列表
- Python 网络编程说明第1/2页
- 详解Python Socket网络编程
- python网络编程学习笔记(一)
- python socket网络编程步骤详解(socket套接字使用)
- python网络编程之TCP通信实例和socketserver框架使用例子
- Android网络编程之获取网络上的Json数据实例
- Java网络编程基础教程之Socket入门实例