网络编程(linux)

TCP建立连接 (可靠传输,丢包重发)
UDP不建立连接 (不可靠传输,丢包不重发)适合:视频点播
网络畅通时,使用UDP较快,不易丢包,阻塞时容易丢包使用TCP
UDP比TCP开销小,没有校验等,速度比TCP快
IP协议是管理路径选择, TCP是管理是否传送正确

为什么TCP是一段一段的发送数据包,是因为不让一直占用端口,页可以和其他需要同端口的一起用。

socket 是网络套接口,TCP 和 UDP想进行网络通信,必须使用它(进程之间通信,不同主机之间通信)
创建套接口成功返回文件描述符(当文件),设备文件不可以定位,普通文件可以定位
传上网络的可以写函数:write, send, sendto
从网上传下来的读函数:read, recv, recvfrom
TCP协议上面三种都可以使用
UDP协议只能使用sendto 和 recvfrom
TCP,IP,网络接口都在内核态
socket是用户态与内核态之间的桥梁

套接口的类型
1.流式套接字(SOCK_STREAM)TCP协议使用
2.数据报套接字(SOCK_DGRAM)UDP协议使用
3.原始套接字(SOCK_RAM)用于测试新的网络协议

IP只能找到主机,端口号区分不同进程

地址结构
在这里插入图片描述
API使用的地址就是这样的类型
在这里插入图片描述
这个是IPV4的类型,使用它之后要强转为上面那个通用类型,因为API使用的是通用类型。

地址转换
在这里插入图片描述
在这里插入图片描述

int inet_pton()
int inet_ntop()
gethostbyname() // 通过输入网址找IP
inet_addt("");//里面写点分字符串,不需要使用字节序转换,其他的就要用字节序转了

计算机都是小端字节序,网络字节序都是大端字节序。
在这里插入图片描述
在传输内容时,如果是字符串就不用转换,因为一个字符就占一个字节不存在高位和地位
如果不是字符串,就需要转了。

TCP模型
客户端:用connect, socket函数
服务器:用listen accept,socket函数
socket创建的接口是主动建立请求
listen:两个功能,一是监听队列长度,二是把socket创建的主动变为被动
accept是建立连接
bind:绑定IP地址和端口号到socket上(绑定的是自己的地址)
客户端和服务器都可以使用,客户端可用可以不用,服务器端必须使用
connect也需要配置地址,这个地址是需要连接的地址
accept返回的是一个套接口,是连接套接口,用于通信,参数是套接口(监听)

TCP(网络通信)
1.创建
int socket(    ,    ,      )
2.配置地址
在这里插入图片描述
3.绑定
在这里插入图片描述
无法绑定问题?
为什么无法绑定,因为服务器有TIME_WAIT函数,突然关闭服务器之后,在启动就无法绑定,要等半分钟,因为服务器关闭之后,要等半分钟套接口绑定才会消失。
客户端下线,服务器怎么知道
1.看套接口返回值
2.客户端发信息。
重复绑定需要在socket() 和bind之间插入
在这里插入图片描述
第一个参数:套接口
第二个参数:绑定那一层
第三个参数:允许地址重复绑定
第四个参数:opt
第五个参数:opt大小

4.监听
在这里插入图片描述
5.accept()
在这里插入图片描述
accept返回值是一个新的套接口,用于专门与客户端连接。
connect函数是客户端主动连接服务器,在此之前要配置服务器地址(这个地址配置不能是任意的,只能是唯一的)
在这里插入图片描述

6.sendto 和 recvfrom函数
在这里插入图片描述
在这里插入图片描述

TCP连接

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>

#define SERVPORT 8888

//服务器  TCP

int main(int argc, char **argv)
{
    int listenfd, connfd;      //定义套接口,两个套接口,一个监听,一个是传输用的
    char buf[100];             //缓冲区
    int n;                     //返回值,字节数
    socklen_t len;             //客户端地址长度
    struct sockaddr_in servaddr,cliaddr;  //地址结构类型,客户端和服务器端

    //创建套接口
    listenfd = socket(AF_INET, SOCK_STREAM, 3);//地址协议类型IPV4,协议类型(TCP,), 0

    bzero(&servaddr, sizeof(servaddr));   //将服务器地址清空

    //配置地址
    servaddr.sin_family = AF_INET;   //IPV4
    servaddr.sin_port = htons(SERVPORT); //端口号设置
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY); //服务器地址,可以是任意一个

    //绑定服务器地址在套接口上
    bind(listenfd, (struct sockaddr *)&servaddr,sizeof(servaddr));//套接口文件描述符,地址初始位置(注意强制类型转换),地址空间长度
    
    //监听函数,监听多少
    listen(listenfd, 1024);  //套接口文件描述符,监听长度


    for(;;)
    {
        len = sizeof(cliaddr);  //客户端地址长度

        //链接
        connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &len);  //这里长度需要先定义,拿到之后,再取地址,拿到客户端地址长度,返回值是一个套接口

        while(1)
        {
            //接受客户端发过来的消息
            n = recvfrom(connfd, buf, 100, 0, (struct sockaddr *) &cliaddr, &len);

            if(0 == n)
            {
                printf("客户端下线!\n");
                break;
            }
            //到这里我们就可以收到客户端发过来的消息
    
            //对收到的数据进行处理
    
            buf[n] = '\0';   //变成字符串

            printf("*******************\n");
            printf("收到的数据如下:\n");
            printf("%s",buf);

            //大小写转化
            for(int i = 0; buf[i] != '\0'; i++) 
            {
                if(buf[i] >= 'A' && buf[i] <= 'Z') 
                {
                    buf[i] += 32;
                }
                else if(buf[i] >= 'a' && buf[i] <= 'z') 
                {
                    buf[i] -= 32;
                }
            }
       /*     for(int i = 0; buf[i] != '#'; i++) 
            {
                printf("%c",buf[i]);
            }
            */
            printf("*******************\n");

            //处理完就要发送回去
            sendto(connfd, buf, n, 0,(struct sockaddr*)&cliaddr, len);
        }

        //关闭套接口
        close(connfd);

    }


    close(listenfd);

    return 0;
}

#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <arpa/inet.h>

#define SERVPORT 8888

//客户端 TCP

int main(int argc, char **argv)
{
    int sockfd;  //一个套接口皆可以了
    int n; //收到的字节数;
    char sendbuf[100];  //发送缓冲区
    char recvbuf[100];  //接收缓冲区

    struct sockaddr_in servaddr,cliaddr;  //定义结构体变量

    //这里地址从命令行输入
    if(argc != 2)
    {
        printf("need server IP\n");
        exit(-1);
    }

    //创建套接口
    sockfd = socket(AF_INET, SOCK_STREAM, 0);  //地址协议类型,tcp,0

    //清空地址空间
    bzero(&servaddr, sizeof(servaddr));
    
    //配置地址
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(SERVPORT);
    servaddr.sin_addr.s_addr = inet_addr(argv[1]);

    //链接
    connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr));

    //从键盘上获取
    while(fgets(sendbuf,100,stdin) != NULL)
    {
        //发送到服务器
        sendto(sockfd,sendbuf,strlen(sendbuf), 0, (struct sockaddr *) &servaddr,sizeof(servaddr));

        //接收服务器返回的数据
        n = recvfrom(sockfd, recvbuf, 100, 0, NULL, NULL);

        recvbuf[n] = '\0';

        fputs(recvbuf,stdout);

    }


    close(sockfd);
  

    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值