首页 > 其他分享 >学习笔记11

学习笔记11

时间:2023-11-25 17:15:53浏览次数:41  
标签:11 addr 笔记 server 学习 printf 服务器 line include

网络编程是一种涉及计算机网络的软件开发技术,它允许不同计算机之间的通信和数据交换。在网络编程中,TCP/IP协议是基础,它定义了数据如何在网络上进行传输。

TCP/IP协议

TCP/IP(Transmission Control Protocol/Internet Protocol)是一组通信协议,它是互联网通信的基础。主要包括TCP和IP两个子协议。

IP地址和协议

  • IP地址: 每个主机都有一个唯一的32位IP地址,用于在网络中标识其位置。IP地址分为两部分,即网络部分和主机部分。

  • IP协议: 用于在IP主机之间发送和接收数据包。数据包由IP头、发送方IP地址、接收方IP地址以及数据组成。

路由器

  • TTL(Time To Live): IP包中的一个8位生存时间计数,防止数据包在网络中无限循环。每经过一个路由器,TTL减小1,如果减小到0,包会被丢弃。

  • 路由器: 用于接收和转发数据包,将数据包从源主机传输到目标主机。

UDP协议

UDP(User Datagram Protocol)是在IP上运行的协议,用于发送和接收数据报。相对于TCP,UDP不保证可靠性,但速度更快。

  • UDP特点: 快速高效,不保证数据可靠性。常用于实时应用,如视频流、音频等。

TCP协议

TCP(Transmission Control Protocol)是一种面向连接的协议,用于发送和接收数据流。相对于UDP,TCP提供了可靠的数据传输。

  • 端口编号: 多个应用程序可以同时使用TCP,每个应用程序由主机IP、协议(TCP/IP)、端口号唯一标识。

  • TCP连接: 类似于电话连接,通过建立连接来传输数据。通过socket()创建套接字,connect()建立连接,send()recv()进行数据传输。

网络字节序

计算机可以使用大端字节序或小端字节序,为了在网络中正确传输数据,需要进行字节序转换。

  • 大端/小端: 不同计算机体系结构对字节的存储顺序不同。网络字节序通常使用大端字节序。

数据流在TCP/IP网络中的传输

数据在网络中的传输涉及多个层级,从应用层到链路层,分别添加TCP或UDP报头、IP报头、以及网络链路层的帧。

套接字编程

套接字是实现网络编程的接口,使用一系列C语言库函数和系统调用来实现。在UNIX/Linux系统中,套接字API提供了socket()bind()等函数。

  • 套接字地址: 使用struct sockaddr_in定义,包括协议类型、端口号、IP地址等信息。

  • UDP套接字: 使用sendto()recvfrom()进行数据传输。

  • TCP套接字: 使用listen()监听连接请求,accept()接受连接,connect()建立连接,send()recv()进行数据传输。

UDP服务器-客户端程序

UDP服务器 (udp_server.c)

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

#define BUFLEN 256 // 缓冲区最大长度
#define PORT 1234 // 服务器端口号

char line[BUFLEN];
struct sockaddr_in me, client;
int sock, rlen, clen = sizeof(client);

int main() {
    printf("1. 创建一个UDP套接字\n");
    sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);

    printf("2. 填充服务器地址和端口号\n");
    memset((char *)&me, 0, sizeof(me));
    me.sin_family = AF_INET;
    me.sin_port = htons(PORT);
    me.sin_addr.s_addr = htonl(INADDR_ANY); // 使用本地地址

    printf("3. 将套接字绑定到服务器IP和端口\n");
    bind(sock, (struct sockaddr*)&me, sizeof(me));

    printf("4. 等待数据报\n");
    while (1) {
        memset(line, 0, BUFLEN);
        printf("UDP服务器: 等待数据报\n");
        
        // recvfrom() 获取客户端IP和端口信息
        rlen = recvfrom(sock, line, BUFLEN, 0, (struct sockaddr *)&client, &clen);
        printf("从 [主机:端口] = [%s:%d] 收到一个数据报\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port));
        printf("rlen=%d: line=%s\n", rlen, line);

        printf("发送回复\n");
        sendto(sock, line, rlen, 0, (struct sockaddr*)&client, clen);
    }
}

UDP客户端 (udp_client.c)

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

#define SERVER_HOST "127.0.0.1" // 默认服务器IP: 本地主机
#define SERVER_PORT 1234 // 服务器端口号
#define BUFLEN 256 // 缓冲区最大长度

char line[BUFLEN];
struct sockaddr_in server;
int sock, rlen, slen = sizeof(server);

int main() {
    printf("1. 创建一个UDP套接字\n");
    sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);

    printf("2. 填写服务器地址和端口号\n");
    memset((char *)&server, 0, sizeof(server));
    server.sin_family = AF_INET;
    server.sin_port = htons(SERVER_PORT);
    inet_aton(SERVER_HOST, &server.sin_addr);

    while (1) {
        printf("输入一行:");
        fgets(line, BUFLEN, stdin);
        line[strlen(line) - 1] = 0; // 去除末尾的换行符

        printf("向服务器发送数据\n");
        sendto(sock, line, strlen(line), 0, (struct sockaddr *)&server, slen);

        memset(line, 0, BUFLEN);
        printf("尝试从服务器接收一行\n");
        rlen = recvfrom(sock, line, BUFLEN, 0, (struct sockaddr *)&server, &slen);
        printf("rlen=%d: line=%s\n", rlen, line);
    }
}


TCP回显服务器-客户端程序

TCP服务器 (tcp_server.c)

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

#define MAX 256
#define SERVER_PORT 1234

struct sockaddr_in server_addr, client_addr;
int mysock, csock; // socket描述符
int r, len, n; // 辅助变量

int server_init() {
    printf("================== 服务器初始化 ======================\n");

    // 创建TCP套接字
    printf("1: 创建一个TCP流套接字\n");
    mysock = socket(AF_INET, SOCK_STREAM, 0);
    if (mysock < 0) {
        printf("socket调用失败\n");
        exit(1);
    }

    // 填写服务器地址信息
    printf("2: 用主机IP和端口号信息填充server_addr\n");
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY); // 本地主机
    server_addr.sin_port = htons(SERVER_PORT);

    // 将套接字绑定到服务器地址
    printf("3: 将套接字绑定到服务器地址\n");
    r = bind(mysock, (struct sockaddr *)&server_addr, sizeof(server_addr));
    if (r < 0) {
        printf("绑定失败\n");
        exit(3);
    }

    printf(" 主机名 = %s 端口 = %d\n", SERVER_HOST, SERVER_PORT);
    printf("4: 服务器正在监听....\n");
    listen(mysock, 5); // 队列长度为5

    printf("=================== 初始化完成 =======================\n");
}

int main() {
    char line[MAX];

    server_init();

    while (1) {
        // 尝试接受客户端请求
        printf("服务器: 正在接受新连接....\n");

        // 尝试接受客户端连接,将描述符保存在csock中
        len = sizeof(client_addr);
        csock = accept(mysock, (struct sockaddr *)&client_addr, &len);
        if (csock < 0) {
            printf("服务器: 接受错误\n");
            exit(1);
        }

        printf("服务器: 接受到来自\n");
        printf("-----------------------------------------------\n");
        printf("客户端: IP=%s 端口=%d\n",
               inet_ntoa(client_addr.sin_addr),
               ntohs(client_addr.sin_port));
        printf("-----------------------------------------------\n");

        // 处理循环:client_sock <== data ==> client
        while (1) {
            n = read(csock, line, MAX);
            if (n == 0) {
                printf("服务器: 客户端断开连接,服务器循环\n");
                close(csock);
                break;
            }

            // 显示收到的字符串
            printf("服务器: 读取 n=%d 字节; line=%s\n", n, line);

            // 将字符串回送给客户端
            n = write(csock, line, MAX);
            printf("服务器: 写入 n=%d 字节; ECHO=%s\n", n, line);
            printf("服务器: 准备处理下一个请求\n");
        }
    }
}

TCP客户端

(tcp_client.c)

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

#define MAX 256
#define SERVER_HOST "localhost"
#define SERVER_IP "127.0.0.1"
#define SERVER_PORT 1234

struct sockaddr_in server_addr;
int sock, r;

int client_init() {
    printf("======= 客户端初始化 ==========\n");

    printf("1 : 创建一个TCP套接字\n");
    sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock < 0) {
        printf("socket调用失败\n");
        exit(1);
    }

    printf("2 : 用服务器的IP和端口号信息填充server_addr\n");
    // 初始化server_addr结构
    server_addr.sin_family = AF_INET; // 用于TCP/IP
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY); // 本机主机
    server_addr.sin_port = htons(SERVER_PORT); // 端口号1234

    printf("3 : 连接到服务器....\n");
    r = connect(sock, (struct sockaddr *)&server_addr, sizeof(server_addr));
    if (r < 0) {
        printf("连接失败\n");
        exit(3);
    }

    printf("4 : 连接成功\n");
    printf("-------------------------------------------------------\n");
    printf("服务器主机名=%s 端口号=%d\n", SERVER_HOST, SERVER_PORT);
    printf("-------------------------------------------------------\n");
    printf("========= 初始化完成 ==========\n");
}

int main() {
    int n;
    char line[MAX], ans[MAX];

    client_init();

    printf("******** 处理循环 *********\n");
    while (1) {
        printf("输入一行:");
        bzero(line, MAX); // 清零line[]
        fgets(line, MAX, stdin); // 从stdin中获取一行
        line[strlen(line) - 1] = 0; // 去掉末尾的\n

        if (line[0] == 0) // 如果是空行,退出
            exit(0);

        // 发送数据到服务器
        n = write(sock, line, MAX);
        printf("客户端: 写入 n=%d 字节; line=%s\n", n, line);

        // 从sock中读取一行并显示
        n = read(sock, ans, MAX);
        printf("客户端: 读取 n=%d 字节; 回显=%s\n", n, ans);
    }
}

上述程序包含了UDP服务器-客户端和TCP服务器-客户端的代码。这些代码通过套接字编程实现了基本的网络通信。请确保在运行这些程序之前,没有其他程序占用相同的端口号。

苏格拉底挑战




标签:11,addr,笔记,server,学习,printf,服务器,line,include
From: https://www.cnblogs.com/zsy1748774883/p/17855729.html

相关文章

  • 第十二周学习笔记(学习笔记11)
    〇、思维导图一、知识点总结论述TCP/IP协议及其应用,具体包括TCP/IP栈、IP地址、主机名、DNS、IP数据包和路由器;2.介绍TCP/IP网络中的UDP和TCP协议、端口号和数据流;3.阐述服务器—客户机计算模型和套接字编程接口;4.介绍Web和CGI编程,解释HTTP编程模型、Web页面和Web浏览器......
  • 【9.0】Python高级之常用模块学习
    【一】re【二】time、datetime【三】os......
  • OI_problem 玛丽卡_洛谷P1186
    题意一个\(N\)个点\(M\)条边的带边权无向图,要求输出最小的\(V\)使得不管去掉哪一条边,都存在从\(1\)到\(n\)的路径使得边权和不超过\(V\)。思路感觉朴素不太好做,考虑二分。对于一个二分值,即要判断在关于这个值的生成图中,\(1\)和\(n\)在不在一个边双里。考......
  • HanLP 学习
    学习HanLP需要了解,双数组Trie树(Double-arrayTrie)Aho-CorasickDoubleArrayTire算法ACDAT-基于双数组字典树的AC自动机TreeMappipinstallhanlp[full]-ihttps://pypi.tuna.tsinghua.edu.cn/simpleHanLP词性标注集标签含义a形容词ad副形词ag......
  • 机器学习环境安装和使用之01安装库
    安装环境&库pipinstallvirtualenvpipinstallvirtualenvwrapper-win 如果安装的速度慢,则配置pip源:pipconfigsetglobal.index-urlhttps://pypi.tuna.tsinghua.edu.cn/simple/安装库:pip3installnumpypip3installpandaspip3installtablespip3installjupyt......
  • springboot学习之——SpringApplication.run方法
    springboot学习之——SpringApplication.run方法目录springboot学习之——SpringApplication.run方法第一步第二步ConfigurableApplicationContextspringboot版本3.1.5第一步 /** *Statichelperthatcanbeusedtoruna{@linkSpringApplication}fromthe *spe......
  • 学习笔记11+代码
    一、苏格拉底挑战二、遇见的问题三、实践和代码#include<stdio.h>#include<stdlib.h>#include<string.h>#include<sys/socket.h>#include<netdb.h>#include<arpa/inet.h>#include<unistd.h>#defineMAX256#defineSERVER......
  • 强化学习 1
    以下是对李宏毅老师youtube视频-【机器学习2021】概述增强式学习一、二、三简要记录https://www.youtube.com/watch?v=XWukX-ayIrshttps://www.youtube.com/watch?v=US8DFaAZcp4https://www.youtube.com/watch?v=kk6DqWreLeU什么是ReinforcementLearning(RL)?  先回顾一下Su......
  • P1135 奇怪的电梯
    奇怪的电梯题目背景感谢@yummy提供的一些数据。题目描述呵呵,有一天我做了一个梦,梦见了一种很奇怪的电梯。大楼的每一层楼都可以停电梯,而且第\(i\)层楼(\(1\lei\leN\))上有一个数字\(K_i\)(\(0\leK_i\leN\))。电梯只有四个按钮:开,关,上,下。上下的层数等于当前楼层上的那......
  • 信息安全系统设计与实现 学习笔记11
    《Unix/Linux系统编程》13章学习笔记网络编程简介TCP/IP协议、UDP和TCP协议、服务器—客户机计算、HTTP和Web页面、动态Web页面的PHP和CGI编程TCP/IP协议TCP/IP是互联网的基础,TCP代表传输控制协议,IP代表互联网协议。TCP/IP的组织结构分为几个层级,通常称为TCP/IP堆栈。顶层时......