Linux下模拟 TCP 套接字编程

TCP套接字编程步骤

客户端

  1. 创建套接字
  2. 绑定地址信息(不推荐,因为系统会帮你绑定,这样能预防端口冲突)
  3. 向客户端发送连接请求
  4. 发送/接收数据
  5. 关闭套接字

服务端

  1. 创建套接字
  2. 绑定地址信息(客户端必须自己绑定,系统不会帮你)
  3. 将套接字设为监听状。此状态下一旦接收到连接请求,就会创建一个新的 socket 并放入未完成连接队列里面去,等到连接建立完成,就会将它再次转到已完成连接队列里去。(若未完成连接队列已满则新的连接请求会被丢弃,直到腾出空间才再次建立连接)
  4. 获取新连接。从已完成连接队列中取出一个套接字,并返回其操作句柄。(新 socket 中拥有源端的地址信息)
  5. 接收/发送数据
  6. 关闭套接字

注意点:

  1. 监听套接字只负责进行建立连接,而不负责进行通信
  2. 新建套接字负责进行通信
  3. 客户端需要使用多进程或者多线程,因为同一时间可能有多个客户端建立连接(建议使用多进程,因为稳定性和健壮性强)
  4. 多进程中父进程需要注意子进程的退出状态,避免出现僵尸进程
    图示流程
    在这里插入图片描述
    函数接口介绍
1. 创建套接字

int socket(int domain, int type, int protocol);
参数:
domain: 地址域,不同的协议版本有着不同的地址结构
		常用的有 AF_INET(ipv4) AF_INET6(ipv6)
type: 套接字类型  tcp(流式套接字) SOCK_STREAM    udp(数据报套接字)SOCK_DGRAM
protocol: 传输协议, tcp(IPPROTO_TCP)  udp(IPPROTO_UDP)
返回值: 成  套接字的操作句柄    败    -1

2. 为套接字绑定地址信息(绑定自己的)

   客户端不推荐,因为系统会帮助绑定,这样可以避免端口冲突,服务端必须自己绑定
    int bind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen);
    参数:
    sockfd:  套接字的操作句柄
    my_addr: 要绑定的地址信息,这是一个结构体,需要用地址信息给结构体的每一个变量赋值(因为不同的地址结构开头都是一致的,为了避免出错,这里需要进行结构体强转)
    addrlen: 要绑定的地址信息的长度,也就是my_addr这个结构体的长度
返回值: 成 0-1

3. 客户端向服务端发起连接请求

int connect(int sockfd,const struct sockaddr *srv_addr,socklen_t addrlen);
参数:
  sockfd     系统调用的套接字描述符,即由socket函数返回的套接字描述符  
  srv_addr   目的套接字的地址,该套接字地址结构必须包含目的IP地址和目的端口号,即想与之通信的服务器地址  
  addrlen     目的套接字地址的大小
返回值:若成功则为0,若出错则为-1

4. 客户端进入监听状态

int listen(int sockfd, int backlog);
参数:
    sockfd    套接字的操作句柄
    backlog   同一时间的并发连接数,决定同一时间最多接收多少个连接请求
返回值:若成功则返回0,若出错则返回-15.获取新连接(从已完成队列中去一个socket,并返回其操作句柄)

int accept(int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen);
参数:
	cliaddr 和 addrlen 用来返回已连接的对端(客户端)的协议地址;  
 	该函数返回套接字描述符,该描述符连接到调用connect函数的客户端.  
 	 这个新的套接字描述符和原始的套接字描述符sockfd具有相同的套接字类型和地址族,而传给accept函数的套接字描述符sockfd没有关联到这个链接,而是继续保持可用状态并接受其他连接请求.若不关心客户端协议地址,可将cliaddr和addrlen参数设置为NULL,否则,在调用accept之前,应将参数cliaddr设为足够大的缓冲区来存放地址,并且将addrlen设为指向代表这个缓冲区大小的整数指针.accept函数返回时,会在缓冲区填充客户端的地址并更新addrlen所指向的整数为该地址的实际大小.若没有连接请求等待处理,accept会阻塞直到一个请求到来.
返回值:若成功返回套接字描述符,出错返回-16.接收/发送数据

ssize_t recv(int sockfd, char *buf, size_t len, int flags);
ssize_t send(int sockfd, char *data, size_t len, int flags);
参数:
   	buf/data 是要接收/发送数据的首地址
   	flag    0   默认表阻塞
   	len     接收/发送数据的长度
返回值:  成  实际收/发的长度  0  表示一端断开连接  -1  失败

7.关闭套接字

int close(int sockfd)
   	

代码演示

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值