首页 » 开发 » Socket编程

Linux Socket API

socket()

int socket(int family, int type, int protocol);

创建1个TCP Socket:

int sockfd = socket(AF_INET, SOCK_STREAM, 0);

创建1个UDP Socket:

int sockfd = socket(AF_INET, SOCK_DGRAM, 0);

通常protocol参数写0即可,表示由系统选择由family和type组合得出的协议。常见的family和type的具体取值如下:

family说明
AF_INETIPv4协议
AF_INET6IPv6协议
AF_LOCALUnix域协议(Unix domain protocols)
type说明
SOCK_STREAMTCP
SOCK_DGRAMUDP
SOCK_RAWRAW Socket

connect()

int connect(int sockfd, const struct sockaddr* servaddr, socklen_t addrlen);

对TCP而言,connect()引发三次握手。UDP通常直接通过sendto()发送报文而无需connect()。

UDP的connect()出于以下几个考虑:发送报文无需指定目标地址,可用write()/send()代替sendto();接收报文可用read()/recv()/recvmsg()替代recvfrom();可从一个已连接的UDP Socket获取异步错误;可以提高性能:通常每个sendto()的内核调用有3步:建立连接、发送报文、断开连接,对已连接的UDP Socket则只有1次建立和1次断开连接的开销。

错误

errno - 99 - Cannot assign requested address

当作TCP压力测试时,运行压力器的Linux主机在conenct时出现这个错误。 缘故是建立connect时,内核将选择一个临时端口(ephemeral ports),当没有临时端口可用时,就会报此错误。修改

sysctl -w net.ipv4.ip_local_port_range = "1024 65535" 

这样系统最大可以支持6w多个临时端口选择。如果6w个端口还不够用怎么办?你可以使用IP别名技术。 让一台Linux物理机虚拟出多个IP,继而,每个IP上可以绑定6w个port。

性能

如果connect目标地址的family是AF_UNSPEC,则若是TCP将发出RST,若是UDP则将去掉目标地址的关联。 这样的结果是留下一个未连接的socket,如用socket()新创建一样。 如果用AF_UNSPEC代替close(),并将此socket扔到一个pool里,就可实现socket重用, 如此省去一个socket()调用的开销。 应该尽量在read()返回0,即收到对方的FIN包后,再用connect(AF_UNSPEC)关闭连接。可能的应用:反向HTTP代理中,由proxy server发向HTTP server的连接。

参考

TCP协议

分享

0