基本TCP套接字编程

socket函数:

#include<sys/socket.h>

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

返回值:若成功则返回非负描述符,若失败则返回-1

family:协议族IPV4、IPV6等

type:字节流、数据包等

protocol:TCP、UDP等

connect函数:

#include<sys/socket.h>

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

若成功则返回0,失败返回-1

第二个函数参数,套接字地址结构含有服务器的IP地址和端口号

客户在调用connect之前,不必非得调用bind函数,若有需要的话内核会确定源IP地址并选择一个临时端口作为源端口号

如果是TCP套接字,调用connect函数将激发TCP的三次握手过程,而且仅在建立成功或出错时返回

出错返回的三种情况:

1.未收到SYN的响应,重传超时后仍未收到,返回ETIMEDOUT

2.收到RST响应,服务器主机上,指定端口上没有进程在等待或运行(硬错误),返回ECONNREFUSED

3.客户发出的SYN在中间的某个路由器上引发了一个“目的地不可达”的ICMP错误,客户机内核记录重传,超时后返回EHOSTUNREACH/ENETUNREACH错误(按照本地系统的转发表,根本没有到达远程系统的路径或connect调用根本不等待就返回

connect将socket由closed状态转变为syn_sent状态,若成功进入ESTABLISHED状态,若失败,则该套接字不可用,必须关闭

bind函数:

将本地协议地址,赋给套接字,包含IP地址与端口号

#inlude<sys/socket.h>

int bind(int sockfd,const struct sockaddr *myadddr,socklen_t addrlen);

成功返回0,出错返回-1

调用bind,可以指定IP地址或端口,可以两者都指定,也可以都不指定(通配地址、本地IP地址,0,非0)

若让内核来选定一个临时端口号,bind函数并不返回,需要调用getsockname函数来返回协议地址

网络字节序(大端,高位字节在低地址)、主机字节序(小端,地位字节在低地址)

htons转16位,htonl转32位

常见错误:地址已使用

bzero:地址置0

setscockopt:消除端口复用

listen函数:

主动套接字->被动套接字

backlog参数规定了内核应该为相应套接字排队的最大连接数

在socket、bind之后,在accept之前调用

内核为一个给定的监听套接字维护了两个队列 队列之和不超过backlog

1.未完成连接队列(SYN_RCVD)

2.已完成连接队列.(ESTABLISHED)

不要将backlog设置为0,若不希望让任何客户连接至监听套接字,那么就关掉

三次握手正常完成的情况下,未完成连接队列中的任何一项在其中的存留时间就是一个RTT

当一个客户SYN到达后,若队列是满的,TCP就忽略该分节,不发送RST

accept函数:

由TCP服务器调用,用于从已完成连接队列头返回下一个已完成连接,如果已完成连接队列为空,那么进程被投入睡眠(套接字为默认阻塞方式时),若成功则为描述符,失败为-1.

#include<sys/socket.h>

int accept(int sockfd,struct sockaddr *cliaddr,socklen_t *addrlen)

监听套接字与已连接套接字

 

一个问题:非阻塞accept、connect

引用回答:

1.非阻塞accept:

我们一般使用IO复用来实现并发模型,如果我们默认监听套接字为阻塞模式,假设一种场景如下:
客户通过connect向TCP服务器发起三次握手
三次握手完成后,触发TCP服务器监听套接字的可读事件,IO复用返回(select、poll、epoll_wait)
客户通过RST报文取消连接
TCP服务器调用accept接受连接,此时发现内核已连接队列为空(因为唯一的连接已被客户端取消)
程序阻塞在accept调用,无法响应其它已连接套接字的事件
为了防止出现上面的场景,我们需要把监听套接字设置为非阻塞

2.由于程序用select等待连接完成,可以设置一个select等待时间限制,从而缩短connect超时时间。

多数实现中,connect的超时时间在75秒到几分钟之间。有时程序希望在等待一定时间内结束,使用非阻塞connect可以防止阻塞75秒,在多线程网络编程中,尤其必要。


 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值