- TCP是面向连接的传输控制协议,而UDP提供了无连接的数据报服务;
-
TCP具有高可靠性,确保传输数据的正确性,不出现丢失或乱序;UDP在传输数据前不建立连接,不对数据报进行检查与修改,无须等待对方的应答,所以会出现分组丢失、重复、乱序,应用程序需要负责传输可靠性方面的所有工作;
-
UDP具有较好的实时性,工作效率较TCP协议高;
-
UDP段结构比TCP的段结构简单,因此网络开销也小。
-
TCP对系统资源要求较多,UDP对系统资源要求较少
TCP具体编程步骤:
服务器:
(1)、建立套接字:socket。建立点对点的通讯。#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>int socket(int domain, int type, int protocol);
第一个参数:指定域,协议族
AF_UNIX, AF_LOCAL Local communication unix(7) 建立UNIX的协议
AF_INET IPv4 Internet protocols ip(7) 这个代表使用IPV4的协议族 ----> 32bit
AF_INET6 IPv6 Internet protocols ipv6(7) 这个代表使用IPV6的协议族 ----> 128bit第二个参数:指定我们创建的套接字的类型
SOCK_STREAM 提供一种有序的、可靠、双向的,基于连接的字节流类型的一种套接字。 ----> TCP
SOCK_DGRAM 提供一种数据报的通讯方式,这种方式是无连接的,不可靠的,有固定最大数据通讯长度的这一种套接字 ----> UDP
第三个参数:指定该套接字用这个协议族里面的哪个子协议。一般都用0。
返回值:如果成功这个新建的套接字的fd,就会返回。如果出错就会返回-1。
(2)、绑定:bind 绑定我们通讯的地址。#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
第一个参数:就是前面返回的文件描述符。
第二个参数:指定我们通讯的地址,这个是一个通用的结构体,它的地址,由指定的协议族去决定的。
第三个参数:指定的是第二个参数地址的大小。
返回值:
如果成功返回0;
如果失败返回-1;通用的结构体:
struct sockaddr {
sa_family_t sa_family; //指定所用的协议族。
char sa_data[14]; //这里是具体的地址填充的空间。
}
在头文件里面:#include <netinet/in.h>
/* Internet address. */
typedef uint32_t in_addr_t; //表示其IP地址
struct in_addr
{
in_addr_t s_addr; //这个IP地址,实际上是一个32位无符号的数据
};
/* Type to represent a port. */
IP地址的分类:A类、B类、C类、D类、E类(地址包含有网络号+主机号)
将点分式的IP地址,变成我们对应的32位的数据:sockaddr_in.sin_addr = inet_addr("192.168.5.2");
inet_aton("192.168.5.2", &sockaddr_in.sin_addr);描述我们网络socket地址 /* Structure describing an Internet socket address. */
typedef uint16_t in_port_t; //16位的端口号
struct sockaddr_in
{
__SOCKADDR_COMMON (sin_); //协议族
in_port_t sin_port; //端口号 2字节
struct in_addr sin_addr; //IP地址 4字节
unsigned char sin_zero[8]; //填充8个字节,使其和其他的协议族的地址结构体大小一致。
};端口号:
小端的保存方式,低地址保存低位的数据。
大端的保存方式,低地址保存高位的数据。
#include <arpa/inet.h>
h-->host(主机)
n-->network(网络)
l-->代表是32位
s-->代表是16位
htonl();
htons();
ntohl();
ntohs();
(3)、监听:listen#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>int listen(int sockfd, int backlog);
第一个参数:前面新建的fd。
第二个参数:监听队列上最大的请求数。
返回值:
如果成功返回0;
如果失败返回-1;
(4)、接受链接:accept。
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
第一个参数:前面新建的fd。
第二个参数:用来保存客户端的地址信息。
第三个参数:用来保存客户端地址的长度。
返回值:成功的话返回一个新的fd,然后服务器就可以通过这个新的fd和客户端进行通讯。
如果失败返回 -1;
(5)、对数据收发:read、recv ,发送:write、send。
ssize_t read(int fd, void *buf, size_t count);
ssize_t write(int fd, const void *buf, size_t count);
第一个参数:是前面accept函数返回的新的fd。代表我们要和对应的客户端进行通讯。
第二个参数:是我们要发送或者接收的buffer对应的地址。
第三个参数:对应是我们要读取或者写入的数据按字节计算的长度。返回值:成功的话,返回值的大小代表实际读取或者写入的字节数。这个返回值,和count不一定相等。
如果出错的话,返回-1;#include <sys/types.h>
#include <sys/socket.h>ssize_t send(int sockfd, const void *buf, size_t len, int flags);
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
第一个参数:是前面accept函数返回的新的fd。代表我们要和对应的客户端进行通讯。
第二个参数:是我们要发送或者接收的buffer对应的地址。
第三个参数:对应是我们要读取或者写入的数据按字节计算的长度。
第四个参数:一般都是0;
返回值:成功的话,返回值的大小代表实际读取或者写入的字节数。这个返回值,和count不一定相等。
如果出错的话,返回-1;(6)、关闭:close。
客户端:
(1)、建立套接字:socket。(2)、连接需要连接的服务器:connect。
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
第一个参数:就是第一步新建的socket返回的fd。
第二个参数:指定你要链接的服务器的地址(IP+PORT)
第三个参数:这个地址的长度。
返回值:
如果成功返回0;
如果失败返回-1;
(3)、对数据收发:read/recv write/send.(4)、关闭:close。
-
UDP的通讯方式:
-
服务器来说:
(1)新建socket
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>int socket(int domain, int type, int protocol);
第一个参数:指定域,协议族
AF_UNIX, AF_LOCAL Local communication unix(7) 建立UNIX的协议
AF_INET IPv4 Internet protocols ip(7) 这个代表使用IPV4的协议族 ----> 32bit
AF_INET6 IPv6 Internet protocols ipv6(7) 这个代表使用IPV6的协议族 ----> 128bit第二个参数:指定我们创建的套接字的类型
SOCK_STREAM 提供一种有序的、可靠、双向的,基于连接的字节流类型的一种套接字。 ----> TCP
SOCK_DGRAM 提供一种数据报的通讯方式,这种方式是无连接的,不可靠的,有固定最大数据通讯长度的这一种套接字 ----> UDP
第三个参数:指定该套接字用这个协议族里面的哪个子协议。一般都用0。
返回值:如果成功这个新建的套接字的fd,就会返回。如果出错就会返回-1。(2)绑定bind
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
第一个参数:就是前面返回的文件描述符。
第二个参数:指定我们通讯的地址,这个是一个通用的结构体,它的地址,由指定的协议族去决定的。
第三个参数:指定的是第二个参数地址的大小。
返回值:
如果成功返回0;
如果失败返回-1;通用的结构体:
struct sockaddr {
sa_family_t sa_family; //指定所用的协议族。
char sa_data[14]; //这里是具体的地址填充的空间。
}
在头文件里面:#include <netinet/in.h>
/* Internet address. */
typedef uint32_t in_addr_t; //表示其IP地址
struct in_addr
{
in_addr_t s_addr; //这个IP地址,实际上是一个32位无符号的数据
};
/* Type to represent a port. */
IP地址的分类:A类、B类、C类、D类、E类(地址包含有网络号+主机号)
将点分式的IP地址,变成我们对应的32位的数据:sockaddr_in.sin_addr = inet_addr("192.168.5.2");
inet_aton("192.168.5.2", &sockaddr_in.sin_addr);描述我们网络socket地址 /* Structure describing an Internet socket address. */
typedef uint16_t in_port_t; //16位的端口号
struct sockaddr_in
{
__SOCKADDR_COMMON (sin_); //协议族
in_port_t sin_port; //端口号 2字节
struct in_addr sin_addr; //IP地址 4字节
unsigned char sin_zero[8]; //填充8个字节,使其和其他的协议族的地址结构体大小一致。
};端口号:
小端的保存方式,低地址保存低位的数据。
大端的保存方式,低地址保存高位的数据。
#include <arpa/inet.h>
h-->host(主机)
n-->network(网络)
l-->代表是32位
s-->代表是16位
htonl();
htons();
ntohl();
ntohs();
(3)等待客户端发信息过来 recvfrom#include <sys/types.h>
#include <sys/socket.h>ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);
第一个参数:是前面socket函数返回的fd。代表我们要和对应的客户端进行通讯。
第二个参数:是我们要发送或者接收的buffer对应的地址。
第三个参数:对应是我们要读取或者写入的数据按字节计算的长度。
第四个参数:一般都是0;
第五个参数:用来保存客户端的地址信息。
第六个参数:就是前面这个地址的长度。
返回值:成功的话,返回值的大小代表实际读取的字节数。这个返回值,和count不一定相等。
如果出错的话,返回-1;
(4)可以获取到客户端的地址信息之后,大家就可以互相通讯了。(5)通讯结束之后,关闭连接。
客户端来说:
(1)新建socket(2)初始化好地址结构体。
(3)直接发送:sendto
#include <sys/types.h>
#include <sys/socket.h>ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);
第一个参数:是前面socket函数返回的fd。代表我们要和对应的客户端进行通讯。
第二个参数:是我们要发送或者接收的buffer对应的地址。
第三个参数:对应是我们要读取或者写入的数据按字节计算的长度。
第四个参数:一般都是0;
第五个参数:这个是我们要将数据发送到哪里?这个就是接收方的地址。这个参数一定要指定。
第六个参数:就是前面这个地址的长度。
返回值:成功的话,返回值的大小代表实际发送的字节数。这个返回值,和count不一定相等。
如果出错的话,返回-1;(4)等待服务器回信:recvfrom
(5)通讯结束之后,关闭连接。
TCP和UDP的区别
最新推荐文章于 2024-02-08 16:06:19 发布