抱歉,您的浏览器无法访问本站

本页面需要浏览器支持(启用)JavaScript


了解详情 >

运输层协议概述

TCP: ==传输控制协议==面向连接,==可靠==的数据传输协议。

UDP: ==用户数据报协议==无连接,==不可靠==的数据的数据传输协议

IP: 尽力而为交付服务

函数API

接收端_server

socket()套接字

1
2
#include <sys/socket.h>
int scoket(int domain, int type, int protocol);
  • domain:
    1. AF_INET // IPV4
    2. AF_INET6 // IPV6
    3. AF_LOCAL // 本地
    4. AF_ROUTE // 路由
  • type:
    1. SOCK_STREAM // TCP
    2. SOCK_DGRAM // UDP
    3. SOCK_PACKET
    4. SOCK_SEQPACKET
  • protocol:
    1. IPPROTO_TCP
    2. TPPROTO_UDP
    3. IPPROTO_TIPC
    4. 一般为0
  • Return Value:
    • 成功为新的文件描述符,否则-1

bind()帮定IP和端口

1
2
3
#include <sys/types.h>
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *addr, socketlen_t addrlen);
  • sockfd:
    • 是调用socket()返回的文件描述符
  • addr:
    • 是指向数据结构struct sockaddr 的指针,它保存你的地址(即端口和IP地址)信息
  • addrlen:
    • 设置sizeof(struct sockaddr)
  • Return Value:
    • -1 出错
    • 0 没出错

socket相关的结构体

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <sys/socket.h>

struct sockaddr {
sa_family_t sin_family;
char sa_data[14];
};

struct sockaddr_in {
sa_family_t sin_family; /* address family: AF_INET */
in_port sin_port; /* port in network byte order */
struct in_addr sin_addr; /* internet address */
};

/* Internet address. */
struct in_addr {
uint32_t s_addr; /* address in network byte order */
};

与sockaddr相关的函数

1
2
3
4
5
6
7
#include <arpa/inet.h>
uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
uint32_t ntohl(uint32_t netlong);
uint16_t ntohl(uint16_t netlong);
in_addr_t inet_addr(const char *ip);
char *inet_ntoa(struct in_addr in);

主机字节序&网络字节序

主机字节序:就是我们平常说的大端和小端模式

  • 小端模式:低位字节排放在内存的底地址端,高位字节排放在内存的高地址端
  • 大端模式:高位字节排放在内存的底地址端,低位字节排放在内存的高地址端

网络字节序:4个字节的32bit值以下面的次序传输:首先是07bit,最后是2431bit

查看本机是大端模式还是小端模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>

union Un {
char a;
int b;
};

int main() {
union Un k;
k.b = 1;
// 如果是大端,则k.a为0x00,则t.a != 1,反之是小端
if(k.a != 1) printf("大端!");
else printf("小端!");
return 0;
}

可以复制自己电脑测试,我是小端!

linsten()监听socket

1
2
3
#include <sys/types.h>
#include <sys/socket.h>
int listen(int sockfd, int backlog);
  • sockfd 是调用socket()返回的套接字文件描述
  • backlong 是在进入队列中允许的连接数目
  • Return Value 发生错误返回-1,否则返回0

accept()接受连接

1
2
3
#include <sys/types.h>
#include <sys/socket.h>
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
  • accept()用来从sockfd上返回一个新的连接:

    1. 第一个参数sockfd必须是经由socket(), bind(), listen()函数处理后的socket
    2. 第二个参数是一个地址,将保存对端地址到该地址中
    3. 第三个参数是地址长度的地址
  • Return Value:

    • 如果==成功==返回的是一个==新的sockfd==,原来的sockfd依然可以用accept
    • 如果失败,则返回-1

发送端_Client

connect()建立连接

1
2
3
#include <sys/types.h>
#include <sys/socket.h>
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
  • sockfd: 是系统调用socket() 返回的套接字文件描述
  • addr:是保存着==目的端口和IP地址==的数据结构 struct sockaddr.
  • addrlen: 设置为sizeof(struct sockaddr)
  • Return Value: 错误返回-1,否则返回0

connect和accept是一对,分别在客户端和服务执行,在此期间,完成了三次握手操作

send()发送数据

1
2
3
4
5
#include <sys/types.h>
#include <sys/socket.h>
// read 也行
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
  • sockfd:是你想发送数据的套接字描述符
  • msg: 是你想发送的数据指针
  • len: 是数据的长度
  • flags 设置0即可
  • ==sendtop==:主要用在UDP通信中
  • dest_addr:为远端要通信的网络地址
  • addlen: 为地址的长度
  • Return Value: 成功发送的字节数,错误则返回-1,并设置errno

recv()接收数据

1
2
3
4
5
#include <sys/types.h>
#include <sys/socket.h>
// write 也行
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
ssize_t sendto(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
  • sockfd:是要读的套接字描述符
  • buf: 是要读的信息缓冲区
  • len: 是缓冲的最大长度
  • flags: 可以设置为0
  • Return Value: 实际读入缓冲的数据的字节数。在出错的时候返回同时设置==errno==

close()关闭连接

1
2
#include <unistd.h>
int clase(int fd);

三次握手_流程

未命名绘图

四次挥手_流程

评论