单个客户端通过同一端口,创建不同的socket连接不同的服务器可能吗?
4 个回答
TCP/IP四元组(先不聊五元组 七元组的概念)
src_ip:src_port dst_ip:dst_port(源IP地址、目的IP地址、源端口、目的端口)
TCP/IP协议族用这样唯一的四元组来确定两端的通讯
按照你说的, 客户端就要使用端口5000, 行不行, 肯定行啊
socket()创建socket不管你是服务端还是客服端, 只要你创建成功了都会给你分配一个fd
但是......往下看
先说服务端(TCP):
常见的情况下服务端的流程这个样子
socket();
bind();
listen();
accept();
因为大部分服务端会使用知名端口, 毕竟得让人家知道和你哪个端口通讯
bind()一般就干这个事情把端口和socket建立起关联, 这样就可以让人家直接和你服务端指定的端口通讯
如果服务端没有bind()能不能提供服务呢? 其实也能
没有bind()的情况下直接listen();也会让服务端的socket变成LISTENING 状态(netstat -anop | grep LISTENING)
但是端口随机 !
毕竟这样就不太好, 服务端提供服务难道让客户端去猜端口?
再说客户端(TCP):
常见客户端的代码如下
socket();
connect();
其中并没有让客户端的socket和某个具体端口关联
一般都是系统随机分配一个临时端口, 用完了就放弃了
毕竟大部分客户端对于自己用本地哪个端口通信并不在意
但是可不可以作为客户端使用本地的某个端口呢? 肯定可以啊
那么就变成
socket();
bind();
connect();
在五元组中
src_ip:src_port dst_ip:dst_port(源IP地址、目的IP地址、源端口、目的端口)
src_ip:src_port这两个元素就算定下来了
那么剩下不同的服务, 不同的端口, 任意组合, 只要 保证四元组唯一 就可以达到题主提问的"单个客户端通过同一端口,创建不同的socket连接不同的服务器"
貌似是正确的但其实是不太正确的
接下来简单复习下TCP三次握手
当客户端创建完socket之后.
在调用connect()时, 是让客户端socket的状态(netstat)从CLOSED->变为SYN_SENT
如果成功即接收到服务端ACK分节那么客户端的状态就会从SYN_SENT->变为ESTABLISHED(同时回复服务端发来的SYN加1, 作为ACK回复服务端)
如果失败, 那么客户端需要重新调用socket()函数创建新socket, 不能对connect()失败的socket重复调用connect()
所以TCP的情况下, 客户端某个端口的socket能不能做到和不同的服务端通讯?
可以, 但是不能做到同时 . 客户端和某个服务端正在通讯突然想和其他的服务端通讯就得先断开连接然后再重新连接(是不是超麻烦)
那么能不能创建不同的socket bind()相同的端口, 题主你试下就知道了 肯定不行 会提示端口已占用
然后说UDP
UDP这个神奇的东西, 可以做到题主你说的
客户端让UDP和某个端口绑定, 也不用创建多个socket.
就通过这一个socket直接往外发, 和不同的UDP服务通讯
毕竟UDP发送的API长成这样
参数5 const struct sockaddr *dest_addr就是目的地址. 每次调用的时候写不同的地址就好了
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen);