UNP-UNIX网络编程 第四章:基本TCP套接字编程

本文详细介绍了套接字编程的基本概念和技术细节,包括socket、connect、bind等关键函数的使用方法及其返回值含义,深入解析TCP连接的建立过程以及如何进行套接字地址的绑定与监听。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.

#include <sys/socket.h>
int socket(int family, int type, int protocol);
//返回:若成功则返回非负描述符,出错则为-1,family是协议族,type表明套接字类型
family参数指定协议族,也被称为协议域。IPV4:AF_INET、IPV6:AF_INET6。
type参数指定套接字类型。字节流:SOCK_STREAM.   数据报:SOCK_DGRAM。
protocol参数是某个协议类型常值,或者设为0,以选择给定family和type组合的系统默认值。
TCP:IPPROTO_TCP , UDP:IPPROTO_UDP ,SCTP:IPPROTO_SCTP 

2.

connect函数用来建立与TCP服务器的连接。

int connect (int sockfd , const struct sockaddr *servaddr , socklen_t addrlen);
成功:返回0,出错:返回-1

Sockfd: socket返回的套接字描述符;
*servaddr :指向套接字地址结构的指针;
Addrlen:套接字地址结构的大小;

其中出错可能有多种情况:
1.TCP客户没有收到SYN分节的响应,返回ETIMEOUT错误;
2.对客户的SYN的响应是RST(复位),表明主机在指定端口上没有进场等待连接,返回ECONNREFUSED错误;

对于TCP套接字,connect()会触发三次握手过程;当且仅当成功连接或出错时才会返回。其中出错可能有多种情况:
根据TCP转换图,connect()函数会使套接字从CLOSED状态转换到SYN_SENT状态,若成功再转换到ESTABLISHED状态。若connect失败,则该套接字不可再用,必须关闭,然后重新调用socket()函数。

3.

bind()函数把一个本地协议地址赋予一个套接字。(比如端口号)

Int bind (int sockfd ,const struct sockaddr *myaddr , soclen_t addrlen);
成功:返回0,出错:返回-1,还可能:Addrress already in use;

*myaddr:指向套接字地址结构的指针;
Addrlen:套接字地址结构的大小;

对于TCP客户:在该套接字上发送的IP数据报指派了源IP地址。
对于TCP服务器:限定该套接字只接收那些目的地为这个IP地址的客户连接。

4.

int listen (int sockfd , int backlog );

<1>当socket函数创建一个套接字时,它被假设为一个主动套接字(它将调用connect()函数发起连接),

<2>规定内核为相应套将字排队的最大连接个数。(backlog)
对backlog的理解:内核为每个监听套接字维护两个队列:
<1>未完成连接队列, <2>已完成连接队列

5.

int accept (int sockfd , struct sockaddr *cliaddr , socklen_t* addrlen);
成功:返回非负描述符,失败返回-1

功能:由TCP服务器调用,用于从已完成连接队列队头返回下一个已完成连接。
*cliaddr、*addrlen:客户的协议地址及对应大小。
返回的描述符代表与所返回的客户的TCP连接,因此将sockfd称为监听套接字,将返回的描述符称为已连接套接字。

6.

int close( int sockfd);

关闭指定的套接字连接。可以忽略这个,直接exit(-1);

7.

intgetsockname (int sockfd , struct sockaddr *localaddr , socklen_t*addrlen);
intgetpeername (int sockfd , struct sockaddr *peeraddr , socklen_t*addrlen);
成功:返回0,出错返回-1

功能:前者返回套接字的本地端的地址结构,后者返回外地端的地址结构。
只知道connfd的时候,获取客户身份的唯一途径就是调用getpeername。

<1>在没有调用bind的TCP客户上,connect()成功返回后,用getsockname()返回内核赋予该连接的本地IP地址和本地端口号;
<2>以端口号0调用bind(由内核选择本地端口号)后,用getsockname()返回本地端口号;
<3>getsockname可用于获取某个套接字的地址族;
<4>以通配IP地址调用bind的TCP服务器上,与客户的连接建立之后(accept成功返回),
getsockname用于返回内核赋予该连接的本地IP地址。(套接字描述符必须是已连接套接字描述符)
<5>当服务器通过调用accept的某个进程调用exec执行程序时,只能通过getpeername来获取客户身份。

8.

pid_t fork(void);

fork调用一次,在父进程中返回一次,得到子进程的进程ID号,在子进程返回一次,返回0.
父进程在fork之前打开的所以描述符在fork返回后由子进程分享。
如果父进程在fork后得到一个自身的副本,可以调用exec函数将当前进程映像替换成新的程序文件。称调用exec的进程为调用进程,新执行的程序为新程序。
exec函数只有在出错时才返回到调用者,否则,控制就被传递给新程序的起始点,通常是main函数

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值