Linux应用编程——TCP实现文件传输

1、常用编程接口

1.1 socket函数

创建一个套接字

int socket(int domain, int type, int protocol);
  • 入参
    • domain:协议族,如AF_INET表示IPv4。
    • type:套接字类型,如SOCK_STREAM表示TCP套接字。
    • protocol:协议,一般为0。
  • 返回值
    • 成功时返回新创建的套接字的文件描述符,失败时返回-1。

1.2 bind函数 

将套接字绑定到一个IP地址和端口上

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
  • 入参
    • sockfd:套接字文件描述符。
    • addr:指向struct sockaddr_in结构体的指针,包含IP地址和端口信息。
    • addrlenaddr结构体的长度。
  • 返回值
    • 成功时返回0,失败时返回-1。

1.3 listen函数

监听来自客户端的连接请求

int listen(int sockfd, int backlog);
  • 作用:开始监听来自客户端的连接请求。
  • 入参
    • sockfd:套接字文件描述符。
    • backlog:最大连接数。
  • 返回值
    • 成功时返回0,失败时返回-1。

1.4 accpt函数

接受客户端的连接请求,返回一个新的套接字用于通信

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
  • 入参
    • sockfd:套接字文件描述符。
    • addr:指向struct sockaddr_in结构体的指针,用于存储客户端地址信息。
    • addrlenaddr结构体的长度。
  • 返回值
    • 成功时返回新的套接字文件描述符,失败时返回-1。

1.5 send函数

发送数据到套接字

ssize_t send(int sockfd, const void *buf, size_t len, int flags);
  • 入参
    • sockfd:套接字文件描述符。
    • buf:指向要发送数据的缓冲区。
    • len:要发送的数据长度。
    • flags:发送标志,一般为0。
  • 返回值
    • 成功时返回发送的字节数,失败时返回-1。

 1.6 recv函数

从套接字接收数据

ssize_t recv(int sockfd, void *buf, size_t len, int flags);
  • 入参
    • sockfd:套接字文件描述符。
    • buf:用于存储接收数据的缓冲区。
    • len:要接收的数据长度。
    • flags:接收标志,一般为0。
  • 返回值
    • 成功时返回接收的字节数,连接关闭时返回0,失败时返回-1。

 1.7 inet_ntop函数

将网络地址转换为点分十进制格式的字符串表示

const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
  • 入参
    • af:地址族(Address Family),指定地址的类型,常用的有AF_INET(IPv4)和AF_INET6(IPv6)。
    • src:指向存放网络地址的结构体的指针。
    • dst:指向存放转换后点分十进制字符串的缓冲区指针。
    • size:缓冲区的大小。
  • 返回值
    • 成功时返回指向转换后点分十进制字符串的指针(即dst的值)。
    • 失败时返回NULL,并设置errno来指示错误原因。

1.8 inet_pton函数

将点分十进制的字符串转换为网络地址的二进制表示

int inet_pton(int af, const char *src, void *dst);
  • 入参
    • af:地址族,可以是 AF_INET 表示 IPv4 或 AF_INET6 表示 IPv6
    • src:待转换的点分十进制格式的 IP 地址字符串
    • src:待转换的点分十进制格式的 IP 地址字符串
  • 返回值
    • 如果转换成功,返回值为 1
    • 如果传入的地址族不支持或转换失败,返回值为 0
    • 如果出现错误,返回值为 -1

1.9 getdaarinfo函数

根据主机名称和服务名获取地址信息

int getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res);
  • 入参
    • node:主机名或 IP 地址字符串
    • service:服务名或端口号字符串
    • hints:一个指向 struct addrinfo 结构的指针,指定地址解析的参数
    • res:一个指向 struct addrinfo 结构的指针,用于存储解析后的地址信息链表
  • 返回值
    • 如果解析成功,返回值为 0
    • 如果出现错误,返回值为非零值,可以通过 gai_strerror 函数获取错误信息

1.10 getnameinfo函数

根据地址信息获取主机名和服务名 

int getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags);
  • 入参
    • sa:指向 struct sockaddr 结构的指针,包含了套接字地址信息
    • salen:套接字地址结构的长度
    • host:用于存储主机名的缓冲区
    • hostlen:主机名缓冲区的大小
    • serv:用于存储服务名的缓冲区
    • servlen:服务名缓冲区的大小
    • flags:控制解析行为的标志
  • 返回值
    • 如果转换成功,返回值为 0
    • 如果出现错误,返回值为非零值,可以通过 gai_strerror 函数获取错误信息

1.11 inet _addr函数

将点分十进制的字符串转换为IPV4地址的二进制表示 

in_addr_t inet_addr(const char *cp);
  • 入参
    • cp:指向点分十进制格式 IPv4 地址字符串的指针
  • 返回值
    • 如果转换成功,返回值为 32 位 IPv4 地址的网络字节顺序表示
    • 如果传入的字符串格式不正确,返回值为 INADDR_NONE(通常为 -1),表示转换失败

 1.12  memset函数

将一块内存空间的每个字节都设置为指定的值

void *memset(void *s, int c, size_t n);

  • 入参
    • *s:指向要填充的内存块的指针,作用是告诉函数要填充的一块空间的起点在哪
    • c:要填充的值,通常是一个无符号字符,它的作用是告诉函数这块空间要填充成哪个值
    • n:表示要填充的字节数,作用是告诉函数一共需要将多少个字节的空间设置成要填充的值.

  • 返回值
    • 类型是void*(无类型指针),作用是在函数运行结束后返回这块空间的起始地址

2、实现重点

1.怎么将文件名和文件内容发送过去

可以通过结构体将文件进行打包,打包发送过后再对结构体里的信息进行解析。

/*文件信息*/
typedef struct FileMess{
    unsigned long fileLen;
    char fileName[100];
} FileMess;


/*数据包*/
typedef struct DataPack{
    char type;     //'D'表示数据,'M'表示文件信息, 'E'表示错误数据包
    int packSize;   //数据包的大小
    char content[MAXBUFF];  //存放数据
    int contentLen;     //数据的长度
    unsigned long position;    //数据在文件中的位置
    FileMess fileMess;      //文件信息
} DataPack;

2.read每次只能读取一个字节,接收到之后怎么写入。

使用lseek(),重定向到上次写入字节的后边

lseek(fd, recvedCount, SEEK_SET);//重定向
            write(fd, dataPack->content, dataPack->contentLen);
            recvedCount += dataPack->contentLen;

3.实现效果

服务器端

客户端 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值