Linux网络编程之TCP编程

1 CS 模式

  客户端(Client)和服务器(Serve)模式。客户端是主动的,服务器是被动的。一般情况下,一定服务器会响应多个客户端。
在这里插入图片描述

2 TCP网络编程架构

在这里插入图片描述

3 TCP 网络编程相关函数(API)

3.1 创建套接字函数 Socket()

  套接字和无名管道、有名管道、信号灯,共享内存、消息队列、信号灯集都属于进程间通讯方式。套接字一般用于网络通信,其他的一般用于本地通信。

3.1.1 函数原型

#include<sys/types.h>
#include<sys/socket.h>
int socket (int domain, int type, int protocol)

3.1.2 参数

1、domain 是地址族
PF_INET // internet 协议
PF_UNIX // unix internal协议
PF_NS // Xerox NS协议
PF_IMPLINK // Interface Message协议
AF_INET IPv4 Internet protocols ip(7)
AF_INET6 IPv6 Internet protocols ipv6(7)
AF_UNIX, AF_LOCAL Local communication unix(7)
AF_NETLINK Kernel user interface device netlink(7)
AF_PACKET Low level packet interface packet(7)
2、type 套接字类型
SOCK_STREAM // 流式套接字
SOCK_DGRAM // 数据报套接字
SOCK_RAW // 原始套接字
3.protocol: 一般填0,原始套接字编程时需填充

3.1.3 返回值

成功时返回文件描述符,出错时返回为-1。

3.1.4 适用范围

TCP客户端和TCP服务器端。

3.2 IP地址和端口号绑定函数 bind ()

3.2.1 函数原型

#include<sys/types.h>
#include<sys/socket.h>
int bind (int sockfd, struct sockaddr* addr, int addrLen);

3.2.2 参数

1、sockfd: 通过socket()函数拿到的fd;
2、addr: struct sockaddr的结构体变量的地址 ,包含本机IP 地址和端口号。
3、addrlen: 地址长度 。

3.2.3 返回值

成功返回0,失败返回-1。

3.2.4 适用范围

TCP服务器端。

3.2.5 地址相关数据结构体

1、通用地址结构
struct sockaddr
{
u_short sa_family; // 地址族, AF_xxx
char sa_data[14]; // 14字节协议地址
};

2、Internet协议地址结构
struct sockaddr_in
{
u_short sin_family; // 地址族, AF_INET,2 bytes
u_short sin_port; // 端口,2 bytes
struct in_addr sin_addr; // IPV4地址,4 bytes
char sin_zero[8]; // 8 bytes unused,作为填充
};
3、IPv4地址结构
// internet address
struct in_addr
{
in_addr_t s_addr; // u32 network address
};

3.2.6 地址结构体的一般用法

1、定义一个struct sockaddr_in类型的变量并清空
struct sockaddr_in myaddr;
memset(&myaddr, 0, sizeof(myaddr));
2、填充地址信息
myaddr.sin_family = PF_INET;
myaddr.sin_port = htons(8888);
myaddr.sin_addr.s_addr = inet_addr(“192.168.1.100”);
3、将该变量强制转换为struct sockaddr类型在函数中使用
bind(listenfd, (struct sockaddr*)(&myaddr), sizeof(myaddr));

3.3 监听设置函数 listen ()

3.3.1 函数原型

#include<sys/types.h>
#include<sys/socket.h>
int listen (int sockfd, int backlog);

3.3.2 参数

1、sockfd: 通过socket()函数拿到的fd;
2、backlog: 同时允许几路客户端和服务器进行正在连接的过程(正在三次握手)。一般填5,测试得知,ARM最大为8。

内核中服务器的套接字fd会维护2个链表:
A、 正在三次握手的的客户端链表(数量=2backlog+1), 比如:listen(fd, 5); //表示系统允许11(=25+1)个客户端同时进行三次握手。
B、已经建立好连接的客户端链表(已经完成3次握手分配好了newfd)。
C、完成listen()调用后,socket变成了监听socket(listening socket)。

3.3.3 返回值

成功返回0,失败返回-1。

3.3.4 适用范围

TCP服务器端。

3.4 连接函数 accept ()

TCP服务端调用 accept () 函数后,服务器端程序阻塞等待客户端连接请求

3.4.1 函数原型

#include <sys/types.h>
#include <sys/socket.h>
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) ;

3.4.2 参数

1、sockfd: 经过前面socket()创建并通过bind(),listen()设置过的fd
2、 addr:客户端地址,详情参考“3.2.2 IP地址和端口号绑定函数 bind ()参数”;
3、addrlen:客户端地址长度。

3.4.3 返回值

成功时返回已经建立好连接的新的文件描述符fd,失败返回-1。

3.4.4 适用范围

TCP服务器端。

3.5 建立连接函数(客户端)connect ()

3.5.1 函数原型

#include <sys/types.h>
#include <sys/socket.h>
int connect(int sockfd, struct sockaddr *serv_addr, int addrlen);

3.5.2 参数

1、sockfd: 通过socket()函数拿到的fd;
2、serv_addr: 服务器端地址,详情参考“3.2.2 IP地址和端口号绑定函数 bind ()参数”,connect()函数和服务器的bind()函数写法类似;
3、addrlen: 地址长度;

3.5.3 返回值

成功返回0,失败返回-1。

3.5.4 适用范围

TCP客户端。

3.6 数据发送与接收函数 send () 和 recv ()

3.6.1 函数原型

#include <sys/socket.h>
ssize_t send(int socket, const void *buffer, size_t length, int flags);

#include <sys/socket.h>
ssize_t recv(int socket, const void *buffer, size_t length, int flags);

3.6.2 参数

1、socket:最近的socket文件描述符;
2、buffer : 发送/接收的缓冲区首地址;
3、length : 发送/接收的字节数;
3、flags : 发送/接收方式(通常为0)。

3.6.3 返回值

成功:实际发送/接收的字节数;失败:-1, 并设置errno。

3.6.4 适用范围

TCP服务端和TCP客户端。

3.6.5 文件I/O的发送与接收函数

ssize_t read(int fd, void *buf, size_t count);
ssize_t write(int fd, const void *buf, size_t count);
注意:
1、read()和write()经常会代替recv()和send(),通常情况下,看程序员的偏好;
2、使用read()/write()和recv()/send()时最好统一。

3.7 套接字关闭函数 close ()

3.7.1 函数原型

int close(int sockfd);

3.7.2 参数

sockfd:要关闭的套接字文件符。

3.7.3 返回值

成功则返回0.失败则返回-1。

3.7.4 适用范围

TCP服务端和TCP客户端。

3.7.5 shutdown() 与 close ()

一、二者的区别:
1、close函数会关闭套接字ID,如果有其他的进程共享着这个套接字,那么它仍然是打开的,这个连接仍然可以用来读和写,并且有时候这是非常重要的 ,特别是对于多进程并发服务器来说;
  而shutdown会切断进程共享的套接字的所有连接,不管这个套接字的引用计数是否为零,那些试图读得进程将会接收到EOF标识,那些试图写的进程将会检测到SIGPIPE信号,同时可利用shutdown的第二个参数选择断连的方式。
2、TCP连接是双向的(是可读写的),当我们使用close时,会把读写通道都关闭,有时侯我们希望只关闭一个方向,这个时候我们可以使用shutdown。

二、shutdown() 函数详解
1、函数原型
int shutdown(int sockfd, int howto);
2、参数
A、sockfd:要关闭的套接字文件符;
B、howto:howto = 10关闭读通道,但是可以继续往套接字写数据;
howto = 1和上面相反,关闭写通道。只能从套接字读取数据;
howto = 2关闭读写通道,和close()一样。
3、返回值
成功则返回0.失败则返回-1。
4、适用范围
TCP服务端和TCP客户端。

4 TCP服务器端并发编程

  在Linux网络编程CS(客户与服务器)模式下,一个服务器端往往响应多个客户端。当多个客户端同时访问服务器是,服务器就得有并发功能。一下就介绍TCP并发服务器框架。

4.1 TCP 循环服务器框架

  最原始的TCP服务器框架,既不采用多进程,也不采用多线程,一个服务器只能服务一个客户端。这种服务器框架不常用,如下图。

4.2 TCP多进程服务器框架

稳定,效率一般,如下图。源码实现参加华清培训响应章节。

4.3 TCP多线程服务器框架

效率高,不稳定,如下图。源码实现参加华清培训响应章节。

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值