网络编程TCP与UDP

TCP与UDP

UDP头:

包括源端口、目的地端口、用户数据包长度,检验和 数据。

cs 复制代码
typedef struct _UDP_HEADER 
{
 unsigned short m_usSourPort;       // 源端口号16bit
 unsigned short m_usDestPort;       // 目的端口号16bit
 unsigned short m_usLength;        // 数据包长度16bit
 unsigned short m_usCheckSum;      // 校验和16bit
}__attribute__((packed))UDP_HEADER, *PUDP_HEADER;

IP头:

UDP与TCP的区别

|-------------------|----------------------|
| TCP | UDP |
| 有链接 | 无链接 |
| 可靠传输(使用流量控制和拥塞控制) | 不可靠传输(不使用流量控制和用三个控制) |
| 只能一对一 | 一对一,一对多或者多对多 |
| 面向字节流 | 面向报文 |
| 首部大小20~60字节 | 首部大小8字节 |

SOCK_UDP

服务端代码:

cs 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <time.h>
typedef struct sockaddr * (SA);
int main(int argc, char *argv[])
{
    int sockfd = socket(AF_INET,SOCK_DGRAM,0);
    if(-1 == sockfd)
    {
        perror("socket");
        exit(1);
    }

    // man 7 ip 
    struct sockaddr_in ser,cli;
    bzero(&ser,sizeof(ser));
    bzero(&cli,sizeof(cli));
    ser.sin_family = AF_INET;
    // 大小端转化 host to net short 
    ser.sin_port = htons(50000);
    ser.sin_addr.s_addr = inet_addr("192.168.203.128");
    int ret = bind(sockfd,(SA)&ser,sizeof(ser));
    if(-1 == ret)
    {
        perror("bind");
        exit(1);
    }
    socklen_t len = sizeof(cli);
    while(1)
    {
        char buf[512]={0};
        recvfrom(sockfd,buf,sizeof(buf),0,(SA)&cli,&len);
        time_t tm;
        time(&tm);
        sprintf(buf,"%s %s",buf,ctime(&tm));
        sendto(sockfd,buf,strlen(buf),0,(SA)&cli,len);
    }
    close(sockfd);
    return 0;
}

客户端代码:

cs 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <time.h>
typedef struct sockaddr * (SA);


int main(int argc, char *argv[])
{
    int sockfd = socket(AF_INET,SOCK_DGRAM,0);
    if(-1 == sockfd)
    {
        perror("socket");
        exit(1);
    }
    struct sockaddr_in ser;
    bzero(&ser,sizeof(ser));
    ser.sin_family = AF_INET;
    // 大小端转化 host to net short 
    ser.sin_port = htons(50000);
    ser.sin_addr.s_addr = inet_addr("192.168.203.128");

    while(1)
    {
        char buf[512]="hello,this is udp test";
        sendto(sockfd,buf,strlen(buf),0,(SA)&ser,sizeof(ser));
        bzero(buf,sizeof(buf));
        recvfrom(sockfd,buf,sizeof(buf),0,NULL,NULL);
        printf("buf is %s\n",buf);
        sleep(1);
    }
    close(sockfd);
    return 0;
}

网络接口

socket

cs 复制代码
int socket(int domain, int type , int protocol);

socket作用:创建套接字。

domain: 协议族---> 指定了套接字所使用的协议类型(常用的协议族包括 AF_INET、AF_INET6、AF_UNIX等。其中,AF_INET 表示 IPv4 协议族,AF_INET6 表示 IPv6 协议族,AF_UNIX 表示 Unix 域协议族)

type:套接字类型---> 指定了套接字的数据传输方式(SOCK_STREAM 表示面向连接的流套接字,主要用于可靠传输数据,例如 TCP 协议。SOCK_DGRAM 表示无连接的数据报套接字,主要用于不可靠传输数据,例如 UDP 协议。)

protocol:协议类型--->指定了套接字所使用的具体的协议类型

bind

cs 复制代码
int bind( (int sockfd, const struct sockaddr *addr, socklen_t addrlen);

bind作用:绑定套接字,将套接字与网络地址绑7定。

sockfd:为套接字描述符。

addr 表示绑定的地址信息。

addrlen 是绑定地址信息的长度。

sendto

发送数据(会阻塞)

cs 复制代码
int sendto (int s, const void *buf, int len, unsigned int flags, const struct sockaddr *to, int tolen);

sendto作用:把UDP数据包发给指定地址。

s: socket套接字描述符。

buf: UDP数据报缓存地址。(把数据放在哪里存储,或者说发送的数据是什么)

len: UDP数据报长度。(发送长度)

flags: 该参数一般为0。

to: sendto()函数参数,struct sockaddr_in类型,指明UDP数据发往哪里报。

tolen: 对方地址长度,一般为:sizeof(struct sockaddr_in)。

recvfrom

接收数据(不会阻塞)

cs 复制代码
int recvfrom(int s, void *buf, int len, unsigned int flags, struct sockaddr *from, int *fromlen);

recvfrom()作用:从指定地址接收UDP数据报。

s: socket套接字描述符。

buf: UDP数据报缓存地址。(把数据放在哪里存储,或者说发送的数据是什么)

len: UDP数据报长度。(接收长度)

fromlen:recvfrom()函数参数,struct sockaddr_in类型,指明从哪里接收UDP数据报。

struct sockaddr_in结构体

cs 复制代码
struct sockaddr_in {
short int sin_family;                      /* Address family */
unsigned short int sin_port;       /* Port number */
struct in_addr sin_addr;              /* Internet address */
unsigned char sin_zero[8];         /* Same size as struct sockaddr */
};

这个结构体里面包括:

sin_family //代表协议族 在socket只指AF_INET

sin_port //存储端口号

sin_addr //存储IP地址

sin_zero //是为了让sockaddr与sockaddr_in两个数据结构保持大小相同而保留的空字节。

listen监听套接字

cs 复制代码
int listen(int sockfd, int backlog);

功能: 在套接字id上监听等待链接

返回值:成功 0 ; 失败 -1

SOCK_TCP

服务端代码:

cs 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <string.h>
#include <time.h>
typedef struct sockaddr* (SA);
int main(int argc, char *argv[])
{
   
    //监听套接字
    int listfd =  socket(AF_INET,SOCK_STREAM, 0);
    if(-1 == listfd)
    {
        perror("socket");
        exit(1);
    }

    struct sockaddr_in ser,cli;
    bzero(&ser,sizeof(ser));
    bzero(&cli,sizeof(cli));
    ser.sin_family = AF_INET;
    ser.sin_port = htons(50000);
    //host to net long 
    ser.sin_addr.s_addr = htonl(INADDR_ANY);

    int ret = bind(listfd,(SA)&ser,sizeof(ser));
    if(-1 == ret)
    {
        perror("bind");
        exit(1);
    }
    //同一时刻三次握手排队数
    listen(listfd,3);
    socklen_t  len = sizeof(cli);
    //通信套接字 
    int conn = accept(listfd,(SA)&cli,&len);
    if(-1 == conn)
    {
        perror("accept");
        exit(1);
    }

    while(1)
    {
        char buf[512]={0};
        int rd_ret = recv(conn,buf,sizeof(buf),0);
        if(rd_ret<=0)
        {// 0  对方断开连接 -1 错误
            break;
        }
        time_t tm;
        time(&tm);
        sprintf(buf,"%s %s",buf,ctime(&tm));
        send(conn,buf,strlen(buf),0);
        
    }
    close(listfd);
    close(conn);
    return 0;
}

客户端代码:

cs 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <string.h>
#include <time.h>
#include <arpa/inet.h>
typedef struct sockaddr* (SA);

int main(int argc, char *argv[])
{
    int sockfd = socket(AF_INET,SOCK_STREAM,0);
    if(-1 == sockfd)
    {
        perror("socket");
        exit(1);
    }
    struct sockaddr_in ser;
    bzero(&ser,sizeof(ser));
    ser.sin_family = AF_INET;
    ser.sin_port = htons(50000);
    //host to net long 
    ser.sin_addr.s_addr = inet_addr("127.0.0.1");

    int ret = connect(sockfd,(SA)&ser,sizeof(ser));
    if(-1 == ret)
    {
        perror("connect");
        exit(1);
    }
    while(1)
    {
        char buf[512]="hello,this is tcp test";
        send(sockfd,buf,strlen(buf),0);
        bzero(buf,sizeof(buf));
        recv(sockfd,buf,sizeof(buf),0);
        printf("buf :%s\n",buf);
        sleep(1);
    }
    close(sockfd);
    return 0;
}

三次握手和四次挥手

TCP建立连接://三次握手

最开始客户端处于closed状态,服务端处于Listen状态。

第一次握手:客户端发送一个SYN主动打开传输通道,并且说明客户端的初始化序列号ISN,这时客户端处于SYN_SENT状态。

第二次握手:服务器收到客户端发送的SYN报文之后,会用自己的SYN报文作为应答,也指定了自己的初始化序列号ISN(s),同时还会发送ACK应答给客户端,(ACK = ISN + 1),表示自己收到了客户端的SYN,服务端处于SYN_RCVD状态。

第三次握手:客户端收到SYN报文之后,会发送一个ACK报文,把服务器的ISN+1作为应答ACK的值,表示接收到了服务端的SYN,此时客户端和服务端都处于ESTABLISHED状态。此时建立起了连接。

三次握手目的

确保客户端和服务端的收发功能都是正常的。

TCP终止连接://四次挥手

客户端和服务端都可以主动发起挥手动作,若客户端先发送关闭请求,则过程如下:

第一次挥手:客户端发送一个FIN报文,报文指定一个序列号,客户端变成FIN------WAIT1的状态。

第二次挥手:服务端收到FIN之后,给客户端发送ACK报文,把客户端的序列号+1作为ACK回复,此时服务端进入CLOSE_WAIT状态。

第三次挥手:服务端也要断开连接时,发送FIN报文+序列号给客户端,此时服务端进入LAST_ACK状态。

第四次挥手: 服务端收到FIN之后发送ACK = seq+1回复应答,此时客户端处于TIME_WAIT状态,等一段时间确保服务端收到自己的ACK报文之后才会进入CLOSED状态,而服务端收到应答之后直接进入CLOSED状态。

四次挥手目的

保证客户端发送的最后一个ACK报文能到达服务端。确保所有的信息都传输完,最后发送结束信号,通知对方信息已经发完了再结束。

查看网络指令(在ubuntu)

1、ifconfig 查看自己的网络配置

2、netstat -anp 查看当前活动的互联网连接

3、ping 测试网络命令

4、sudo ufw disable/enable //防火墙关闭/打开

5、sudo apt-get install wireshark //网络抓包工具 只有网络设备闭上有数据的收发就会放在这。

6、sudo wireshark //使用抓包工具

相关推荐
码老白3 分钟前
【老白学 Java】Warshipv2.0(二)
java·网络
HackKong14 分钟前
小白怎样入门网络安全?
网络·学习·安全·web安全·网络安全·黑客
vmlogin虚拟多登浏览器24 分钟前
虚拟浏览器可以应对哪些浏览器安全威胁?
服务器·网络·安全·跨境电商·防关联
澜世34 分钟前
2024小迪安全基础入门第三课
网络·笔记·安全·网络安全
ZZZCY20033 小时前
华为ENSP--IP编址及静态路由配置
网络·华为
EasyCVR3 小时前
私有化部署视频平台EasyCVR宇视设备视频平台如何构建视频联网平台及升级视频转码业务?
大数据·网络·音视频·h.265
hgdlip3 小时前
主IP地址与从IP地址:深入解析与应用探讨
网络·网络协议·tcp/ip
珹洺4 小时前
C语言数据结构——详细讲解 双链表
c语言·开发语言·网络·数据结构·c++·算法·leetcode
科技象限4 小时前
电脑禁用U盘的四种简单方法(电脑怎么阻止u盘使用)
大数据·网络·电脑
东方隐侠安全团队-千里4 小时前
网安瞭望台第3期:俄黑客 TAG - 110组织与密码攻击手段分享
网络·chrome·web安全·网络安全