UDP包头:传输信息时把包头和信息发过去(8个字节)
1.源端口号
2.目的端口号
3.长度
4.校验和
UDP特点:
1.不安全不可靠的传输方式
2.UDP资源开销小,实现机制简单
3.UDP是无连接的
2.TCP编程
发端: 收端:
socket socket
bind
listen
connect accept
send recv
recv send
close close
1.函数接口:
1.socket
UDP: socket(AF_INET, SOCK_DGRAM, 0);
TCP: socket(AF_INET, SOCK_STREAM, 0);
2.listen
int listen(int sockfd, int backlog);
功能:
监听发送三次握手连接的套接字,并放入等到处理队列中
参数:
sockfd:套接字文件描述符
backlog:等待队列的大小(最多存放尚未被处理的三次握手请求的个数)
返回值:
成功返回0
失败返回-1
3.accept
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
功能:
处理等待队列中的第一个套接字
参数:
sockfd:套接字文件描述符
addr:存放发送方IP地址的空间首地址
addrlen:存放发送方IP地址的空间大小
返回值:
成功返回一个新的文件描述符
失败返回-1
4.connect
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
功能:
向接收方发起连接请求
参数:
sockfd:套接字文件描述符
addr:接收方的IP地址和端口号
addrlen:接收方的IP地址和端口号的大小
返回值:
成功返回0
失败返回-1
5.send
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
功能:
向接收方发送数据
参数:
sockfd:套接字文件描述符
buf:要发送的数据的首地址
len:要发送的数据的长度
flags:标志位
返回值:
成功返回发送字节数
失败返回-1
#include "../head.h"
int main(void)
{
int sockfd = 0;
int ret = 0;
struct sockaddr_in recvaddr;
char tmpbuff[4096] = {0};
ssize_t nsize = 0;
recvaddr.sin_family = AF_INET;
recvaddr.sin_port = htons(RECV_PORT);
recvaddr.sin_addr.s_addr = inet_addr(RECV_IP);
//1.创建套接字
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (-1 == sockfd)
{
perror("fail to socket");
return -1;
}
//2.发送连接请求
ret = connect(sockfd, (struct sockaddr *)&recvaddr, sizeof(recvaddr));
if (-1 == ret)
{
perror("fail to connect");
return -1;
}
printf("连接成功\n");
//3.发送数据
fgets(tmpbuff, sizeof(tmpbuff), stdin);
tmpbuff[strlen(tmpbuff)-1] = '\0';
nsize = send(sockfd, tmpbuff, strlen(tmpbuff), 0);
if (-1 == nsize)
{
perror("fail to send");
return -1;
}
printf("发送成功!\n");
//4.接收数据
memset(tmpbuff, 0, sizeof(tmpbuff));
nsize = recv(sockfd, tmpbuff, sizeof(tmpbuff), 0);
if (-1 == nsize)
{
perror("fail to recv");
return -1;
}
printf("实际接收 %ld个字节, 内容:%s\n", nsize, tmpbuff);
//5.关闭
close(sockfd);
return 0;
}
6.recv
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
功能:
接收发送方发送的数据
参数:
sockfd:套接字文件描述符
buf:接收数据的缓冲区首地址
len:接收数据的缓冲区的大小
flags:标志位
返回值:
成功返回实际接收字节数
失败返回-1
对方关闭返回0
#include "../head.h"
int main(void)
{
int sockfd = 0;
int confd = 0;
int ret = 0;
char tmpbuff[4096] = {0};
struct sockaddr_in recvaddr;
ssize_t nsize = 0;
recvaddr.sin_family = AF_INET;
recvaddr.sin_port = htons(RECV_PORT);
recvaddr.sin_addr.s_addr = inet_addr(RECV_IP);
//1.创建套接字
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (-1 == sockfd)
{
perror("fail to socket");
return -1;
}
//2.绑定IP地址和端口号
ret = bind(sockfd, (struct sockaddr *)&recvaddr, sizeof(recvaddr));
if (-1 == ret)
{
perror("fail to bind");
return -1;
}
//3.监听
ret = listen(sockfd, 10);
if (-1 == ret)
{
perror("fail to listen");
return -1;
}
//4.处理连接请求
confd = accept(sockfd, NULL, NULL);
if (-1 == confd)
{
perror("fail to accept");
return -1;
}
//5.收发
nsize = recv(confd, tmpbuff, sizeof(tmpbuff), 0);
if (-1 == nsize)
{
perror("fail to recv");
return -1;
}
printf("RECV:%s\n", tmpbuff);
memset(tmpbuff, 0, sizeof(tmpbuff));
fgets(tmpbuff, sizeof(tmpbuff), stdin);
tmpbuff[strlen(tmpbuff)-1] = '\0';
nsize = send(confd, tmpbuff, strlen(tmpbuff), 0);
if (-1 == nsize)
{
perror("fail to recv");
return -1;
}
//6.关闭
close(confd);
close(sockfd);
return 0;
}