网络编程 —— TCP 和 UDP 编程详解

目录

网络编程主要函数介绍

1. socket 函数

2. bind 函数

3. listen 函数

4. accept 函数

5. connect 函数

6. send 函数

7. recv 函数

8. recvfrom 函数

9. sendto 函数

TCP 和 UDP 原理上的区别

TCP 编程

服务端代码:

客户端代码:

UDP 编程

服务端代码:

客户端代码:


网络编程主要函数介绍

1. socket 函数

int socket(int domain, int type,int protocol);

此函数用于创建一个套接字

domain 是网络程序所在的主机采用的通讯协族(AF_UNIX 和 AF_INET 等)。

  • AF_UNIX 只能够用于单一的 Unix 系统进程间通信,而 AF_INET 是针 对 Internet 的,因而可以允许远程通信使用。

type 是网络程序所采用的通讯协议(SOCK_STREAM,SOCK_DGRAM 等)。

  • SOCK_STREAM 表明用的是 TCP 协议,这样会提供按顺序的,可靠,双向,面向连接的比特流。
  • SOCK_DGRAM 表明用的是 UDP 协议,这样只会提不可靠,无连接的通信。

关于 protocol,由于指定了 type,所以这个地方一般只要用 0 来代替就可以了。

此函数执行成功时返回文件描述符,失败时返回-1,看 errno 可知道出错的详细情况

2. bind 函数

int bind(int sockfd, struct sockaddr *my_addr, int addrlen);

从函数用于将地址绑定到一个套接字。

sockfd 是由 socket 函数调用返回的文件描述符。

my_addr 是一个指向 sockaddr 的指针。

addrlen 是 sockaddr 结构的长度。

sockaddr 的定义:

struct sockaddr{

unisgned short as_family;

char sa_data[14];

};

不 过 由 于 系 统 的 兼 容 性 , 我 们 一 般 使 用 另 外 一 个 结 构 (struct sockaddr_in) 来代替。 sockaddr_in 的定义:

struct sockaddr_in{

unsigned short  sin_family;

unsigned short  sin_port;

struct in_addr    sin_addr; // // 结构体套结构体 sin_addr.s_addr

unsigned char   sin_zero[8];

}

如果使用 Internet 所以 sin_family 一般为 AF_INET。

sin_addr 设置为 INADDR_ANY 表示可以和任何的主机通信。

sin_port 是要监听的端口号。

bind 将本地的端口同 socket 返回的文件描述符捆绑在一起.

成功则返回 0, 失败则情况和 socket 一样。

3. listen 函数

int listen(int sockfd,int backlog);

此函数宣告服务器可以接受连接请求。

sockfdbind 后的文件描述符。

backlog 设置请求排队的最大长度。当有多个客户端程序和服务端相连时, 使用这个表示可以介绍的排队长度。

listen 函数将 bind 的文件描述符变为监听套接字,返回的情况和 bind 一 样。

4. accept 函数

int accept(int sockfd, struct sockaddr *addr,int *addrlen);

服务器使用此函数获得连接请求,并且建立连接。

addr,addrlen 是用来给客户端的程序填写的,服务器端只要传递指针就可以了, bind,listen 和 accept 是服务器端用的函数。

accept 调用时,服务器端的程序会一直阻塞到有一个客户程序发出了连接。

accept 成功时返回最后的服务器端的文件描述符,这个时候服务器端可以向该描述符写信息了,失败时返回-1 。

5. connect 函数

int connect(int sockfd, struct sockaddr * serv_addr,int addrlen);

可以用 connect 建立一个连接,在 connect 中所指定的地址是想与之通信的服务器的地址。

sockfd 是 socket 函数返回的文件描述符。

serv_addr 储存了服务器端的连接信息,其中 sin_add 是服务端的地址。

addrlen 是 serv_addr 的长度

connect 函数是客户端用来同服务端连接的.成功时返回 0,sockfd 是同服 务端通讯的文件描述符,失败时返回-1。

6. send 函数

ssize_t send(int sockfd, const void *buf, size_t len, int flags);

sockfd 指定发送端套接字描述符;

buf 指明一个存放应用程序要发送数据的缓冲区;

len 指明实际要发送的数据的字节数;

flags 一般置 0。

客户或者服务器应用程序都用 send 函数来向 TCP 连接的另一端发送数据

7. recv 函数

ssize_t recv(int sockfd, void *buf, size_t len, int flags);

sockfd 指定接收端套接字描述符;

buf 指明一个缓冲区,该缓冲区用来存放 recv 函数接收到的数据;

len 指明 buf 的长度;

flags 一般置 0。

客户或者服务器应用程序都用 recv 函数从 TCP 连接的另一端接收数据。

8. recvfrom 函数

ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr,  socklen_t *addrlen);

recvfrom 通常用于无连接套接字,因为此函数可以获得发送者的地址。

src_addr 是一个 struct sockaddr 类型的变量,该变量保存源机的 IP 地址及端口号。

addrlen 常置为 sizeof (struct sockaddr)。

9. sendto 函数

ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,

                                 const struct sockaddr *dest_addr, socklen_t addrlen);

sendto 和 send 相似,区别在于 sendto 允许在无连接的套接字上指定一个目标地址。

dest_addr 表示目地机的 IP 地址和端口号信息,

addrlen 常常被赋值为 sizeof (struct sockaddr)

sendto 函数也返回实际发送的数据字节长度或在出现发送错误时返回-1。

TCP 和 UDP 原理上的区别

TCP 向它的应用程序提供了面向连接的服务。这种服务有 2 个特点:可靠传输、流量控制(即发送方/接收方速率匹配)。它包括了应用层报文划分为短报文, 并提供拥塞控制机制。

UDP 协议向它的应用程序提供无连接服务。它没有可靠性,没有流量控制, 也没有拥塞控制。

TCP 编程

服务端运用到的函数:

  • 1. socket
  • 2. bind 
  • 3. listen
  • 4. accept
  • 5. recv

服务端代码:

#include <sys/types.h>         
#include <sys/socket.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>/* socket* bind* listen* accept* send/recv*/#define SERVER_PORT 8888
#define BACKLOG     10int main(int argc, char **argv)
{int iSocketServer;int iSocketClient;struct sockaddr_in tSocketServerAddr;struct sockaddr_in tSocketClientAddr;int iRet;int iAddrLen;int iRecvLen;unsigned char ucRecvBuf[1000];int iClientNum = -1;signal(SIGCHLD,SIG_IGN); // 信号量,避免出现僵尸进程// 创建服务端套接字iSocketServer = socket(AF_INET, SOCK_STREAM, 0);if (-1 == iSocketServer){printf("socket error!\n");return -1;}// 设置服务器地址信息tSocketServerAddr.sin_family      = AF_INET;tSocketServerAddr.sin_port        = htons(SERVER_PORT);  /* host to net, short */tSocketServerAddr.sin_addr.s_addr = INADDR_ANY;memset(tSocketServerAddr.sin_zero, 0, 8);// 绑定套接字到指定地址和端口iRet = bind(iSocketServer, (const struct sockaddr *)&tSocketServerAddr, sizeof(struct sockaddr));if (-1 == iRet){printf("bind error!\n");return -1;}// 监听连接请求	iRet = listen(iSocketServer, BACKLOG);if (-1 == iRet){printf("listen error!\n");return -1;}while (1){iAddrLen = sizeof(struct sockaddr);iSocketClient = accept(iSocketServer, (struct sockaddr *)&tSocketClientAddr, &iAddrLen); // 接受客户端连接if (-1 != iSocketClient){iClientNum++;printf("Get connect from client %d : %s\n",  iClientNum, inet_ntoa(tSocketClientAddr.sin_addr));if (!fork()){/* 子进程的源码 */while (1){/* 接收客户端发来的数据并显示出来 */iRecvLen = recv(iSocketClient, ucRecvBuf, 999, 0);if (iRecvLen <= 0){close(iSocketClient);return -1;}else{ucRecvBuf[iRecvLen] = '\0';printf("Get Msg From Client %d: %s\n", iClientNum, ucRecvBuf);}}				}}}close(iSocketServer);return 0;
}

客户端运用到的函数:

  • 1. socket
  • 2. connect
  • 3. send

客户端代码:

#include <sys/types.h>        
#include <sys/socket.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>/* socket* connect* send/recv*/#define SERVER_PORT 8888int main(int argc, char **argv)
{int iSocketClient;struct sockaddr_in tSocketServerAddr;int iRet;unsigned char ucSendBuf[1000];int iSendLen;if (argc != 2){printf("Usage:\n");printf("%s <server_ip>\n", argv[0]);return -1;}// 创建客户端套接字iSocketClient = socket(AF_INET, SOCK_STREAM, 0);// 设置服务器地址信息tSocketServerAddr.sin_family      = AF_INET;tSocketServerAddr.sin_port        = htons(SERVER_PORT);  // host to net 端口号if (0 == inet_aton(argv[1], &tSocketServerAddr.sin_addr)) //  ASCLL to net 把argv[1]存到地址中去{printf("invalid server_ip\n");return -1;}memset(tSocketServerAddr.sin_zero, 0, 8); // 清0iRet = connect(iSocketClient, (const struct sockaddr *)&tSocketServerAddr, sizeof(struct sockaddr));	if (-1 == iRet){printf("connect error!\n");return -1;}while (1){if (fgets(ucSendBuf, 999, stdin)) // 从输入流stdin即输入缓冲区中读取999个字符到sendbuf中{iSendLen = send(iSocketClient, ucSendBuf, strlen(ucSendBuf), 0);if (iSendLen <= 0){close(iSocketClient);return -1;}}}return 0;
}

编译执行结果:

UDP 编程

服务端运用到的函数:

  • 1. socket
  • 2. bind 
  • 3. listen
  • 4. accept
  • 5. recv

服务端代码:

#include <sys/types.h>         
#include <sys/socket.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>/* socket* bind* sendto/recvfrom*/#define SERVER_PORT 8888int main(int argc, char **argv)
{int iSocketServer;int iSocketClient;struct sockaddr_in tSocketServerAddr;struct sockaddr_in tSocketClientAddr;int iRet;int iAddrLen;int iRecvLen;unsigned char ucRecvBuf[1000];int iClientNum = -1;iSocketServer = socket(AF_INET, SOCK_DGRAM, 0);if (-1 == iSocketServer){printf("socket error!\n");return -1;}tSocketServerAddr.sin_family      = AF_INET;tSocketServerAddr.sin_port        = htons(SERVER_PORT);  /* host to net, short */tSocketServerAddr.sin_addr.s_addr = INADDR_ANY;memset(tSocketServerAddr.sin_zero, 0, 8);iRet = bind(iSocketServer, (const struct sockaddr *)&tSocketServerAddr, sizeof(struct sockaddr));if (-1 == iRet){printf("bind error!\n");return -1;}while (1){iAddrLen = sizeof(struct sockaddr);iRecvLen = recvfrom(iSocketServer, ucRecvBuf, 999, 0, (struct sockaddr *)&tSocketClientAddr, &iAddrLen);if (iRecvLen > 0){ucRecvBuf[iRecvLen] = '\0';printf("Get Msg From %s : %s\n", inet_ntoa(tSocketClientAddr.sin_addr), ucRecvBuf);}}close(iSocketServer);return 0;
}

客户端运用到的函数:

  • 1. socket
  • 2. connect
  • 3. send

客户端代码:

#include <sys/types.h>         
#include <sys/socket.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>/* socket* connect* send/recv*/#define SERVER_PORT 8888int main(int argc, char **argv)
{int iSocketClient;struct sockaddr_in tSocketServerAddr;int iRet;unsigned char ucSendBuf[1000];int iSendLen;int iAddrLen;if (argc != 2){printf("Usage:\n");printf("%s <server_ip>\n", argv[0]);return -1;}iSocketClient = socket(AF_INET, SOCK_DGRAM, 0);tSocketServerAddr.sin_family      = AF_INET;tSocketServerAddr.sin_port        = htons(SERVER_PORT);  /* host to net, short */if (0 == inet_aton(argv[1], &tSocketServerAddr.sin_addr)){printf("invalid server_ip\n");return -1;}memset(tSocketServerAddr.sin_zero, 0, 8);#endifwhile (1){if (fgets(ucSendBuf, 999, stdin)){iAddrLen = sizeof(struct sockaddr);iSendLen = sendto(iSocketClient, ucSendBuf, strlen(ucSendBuf), 0,(const struct sockaddr *)&tSocketServerAddr, iAddrLen);if (iSendLen <= 0){close(iSocketClient);return -1;}}}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/192288.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android设计模式--工厂模式

一&#xff0c;定义 工厂模式与Android 设计模式--单例模式-CSDN博客&#xff0c;Android设计模式--Builder建造者模式-CSDN博客&#xff0c;Android设计模式--原型模式-CSDN博客 一样&#xff0c;都是创建型设计模式。 工厂模式就是定义一个用于创建对象的接口&#xff0c;让…

225.用队列实现栈(LeetCode)

思路 思路&#xff1a;用两个队列实现栈后进先出的特性 &#xff0c;两个队列为空时&#xff0c;先将数据都导向其中一个队列。 当要模拟出栈时&#xff0c;将前面的元素都导入另一个空队列&#xff0c;再将最后一个元素移出队列 实现 实现&#xff1a; 因为C语言没有库可以…

uni-app报错“本应用使用HBuilderX x.x.x 或对应的cli版本编译,而手机端SDK版本是x.x.x不匹配的版本可能造成应用异常”

uniapp开发的一个跨平台软件&#xff0c;在安卓模拟器上启动的时候报警告&#xff1a; 官方给的解释&#xff1a;uni-app运行环境版本和编译器版本不一致的问题 - DCloud问答 解决办法有两个 方法一&#xff1a;添加忽略警告的配置 项目根目录下找到 manifest.json&#xf…

LeetCode算法心得——高级访客(模拟枚举+小窗口)

大家好&#xff0c;我是晴天学长&#xff0c;今天的周赛第二题&#xff0c;需要的小伙伴可以关注支持一下哦&#xff01;后续会继续更新的。&#x1f4aa;&#x1f4aa;&#x1f4aa; 1) .高级访客 给你一个长度为 n 、下标从 0 开始的二维字符串数组 access_times 。对于每个 …

Spark SQL编程

1. Spark SQL概述 1.1 什么是Spark SQL Spark SQL是用于结构化数据处理的Spark模块。与基本的Spark RDD API不同&#xff0c;Spark SQL提供的接口为Spark提供了有关数据结构和正在执行的计算的更多信息。在内部&#xff0c;Spark SQL使用这些额外的信息来执行额外的优化。与Spa…

一文讲清生产质量场景的数据分析思路及案例实战

今天&#xff0c;顺着制造业数据分析这个大主题&#xff0c;我们来讲讲质量管理数据分析。   说起质量管理&#xff0c;就是对所生产的产品质量进行管理&#xff0c;其最终目的就是保证客户收到的产品质量&#xff0c;提高客户满意度&#xff0c;减少退货和维修的数量。质量管…

Netty Review - 从BIO到NIO的进化推演

文章目录 BIODEMO 1DEMO 2小结论单线程BIO的缺陷BIO如何处理并发多线程BIO服务器的弊端 NIONIO要解决的问题模拟NIO方案一&#xff1a; &#xff08;等待连接时和等待数据时不阻塞&#xff09;方案二&#xff08;缓存Socket&#xff0c;轮询数据是否准备好&#xff09;方案二存…

【计算机网络笔记】CIDR与路由聚合

系列文章目录 什么是计算机网络&#xff1f; 什么是网络协议&#xff1f; 计算机网络的结构 数据交换之电路交换 数据交换之报文交换和分组交换 分组交换 vs 电路交换 计算机网络性能&#xff08;1&#xff09;——速率、带宽、延迟 计算机网络性能&#xff08;2&#xff09;…

日历应用程序 BusyCal mac中文版软件特点

BusyCal mac是一款日历应用程序&#xff0c;它可以帮助用户轻松地管理日程安排、事件提醒、会议安排等。BusyCal 支持 macOS 和 iOS 平台&#xff0c;并且可以与 iCloud、Google 日历、Exchange 等多种日历服务进行同步。 BusyCal mac软件特点 强大的日历功能&#xff1a;Busy…

单链表经典OJ题(三)

目录 1、反转链表 2、合并两个有序链表 3、链表的中间结点 4、环形链表的约瑟夫问题 5、移除链表元素 6、移除元素 1、反转链表 206. 反转链表 - 力扣&#xff08;LeetCode&#xff09; 翻转链表的实质就是更改当前结点的前驱结点和后继结点 假设原链表为:1->2->…

【nlp】2.4 GRU模型

GRU模型 1 GRU介绍2 GRU的内部结构图2.1 GRU结构分析2.2 Bi-GRU介绍2.3 使用Pytorch构建GRU模型2.4 GRU优缺点3 RNN及其变体1 GRU介绍 GRU(Gated Recurrent Unit)也称门控循环单元结构, 它也是传统RNN的变体, 同LSTM一样能够有效捕捉长序列之间的语义关联, 缓解梯度消失或爆…

Day29力扣打卡

打卡记录 美丽塔 II&#xff08;前后缀分解 单调栈&#xff09; 链接 大佬的题解 class Solution:def maximumSumOfHeights(self, a: List[int]) -> int:n len(a)suf [0] * (n 1)st [n] # 哨兵s 0for i in range(n - 1, -1, -1):x a[i]while len(st) > 1 and …

​TechSmith Camtasia 2024破解版功能介绍及使用教程

在现在的网络互联网时代&#xff0c;越来越多的人走上了自媒体的道路。有些自媒体人会自己在网络上录制精彩视频&#xff0c;也有一些人会将精彩、热门的电影剪辑出来再加上自己给它的配音&#xff0c;做成大家喜欢看的电影剪辑片段。相信不管大家是自己平时有独特的爱好也好、…

Django(五、视图层)

文章目录 一、视图层1.视图函数返回值的问题2.三板斧的使用结论&#xff1a;在视图文件中写视图函数的时候不能没有返回值&#xff0c;默认返回的是None&#xff0c;但是页面上会报错&#xff0c;用来处理请求的视图函数都必须返回httpResponse对象。 二、JsonReponse序列化类的…

[单片机课程设计报告汇总] 单片机设计报告常用硬件元器件描述

[单片机课程设计必看] 单片机设计报告常用描述 硬件设计 AT89C51最小系统 AT89C51是美国ATMEL公司生产的低电压&#xff0c;高性能CMOS16位单片机&#xff0c;片内含4k bytes的可反复擦写的只读程序存储器和128 bytes的随机存取数据存储器&#xff0c;期间采用ATMEL公司的高…

FreeRTOS源码阅读笔记3--queue.c

消息队列可以应用于发送不定长消息的场合&#xff0c;包括任务与任务间的消息交换&#xff0c;队列是 FreeRTOS 主要的任务间通讯方式&#xff0c;可以在任务与任务间、中断和任务间传送信息&#xff0c;发送到 队列的消息是通过拷贝方式实现的&#xff0c;这意味着队列存储…

Python入门:一文详解Python列表(List)操作方法

文章目录 前言一、创建一个列表二、访问列表中的值三、更新列表四、删除列表元素六、Python列表截取七、Python列表操作的函数和方法关于Python技术储备一、Python所有方向的学习路线二、Python基础学习视频三、精品Python学习书籍四、Python工具包项目源码合集①Python工具包②…

部署百川大语言模型Baichuan2

Baichuan2是百川智能推出的新一代开源大语言模型&#xff0c;采用 2.6 万亿 Tokens 的高质量语料训练。在多个权威的中文、英文和多语言的通用、领域 benchmark 上取得同尺寸最佳的效果。包含有 7B、13B 的 Base 和 Chat 版本&#xff0c;并提供了 Chat 版本的 4bits 量化。 模…

网络运维Day16

文章目录 Docker简介什么是容器命名空间&#xff1a; Docker 的优缺点 Docker安装Docker镜像管理什么是镜像镜像管理 Docker容器管理运行容器容器启动、停止、重启拷贝文件进入容器容器与应用 DockerfileDockerfile 语法案例 总结 Docker简介 什么是容器 容器是用来装东西的&a…

Python-Python高阶技巧:HTTP协议、静态Web服务器程序开发、循环接收客户端的连接请求

版本说明 当前版本号[20231114]。 版本修改说明20231114初版 目录 文章目录 版本说明目录HTTP协议1、网址1.1 网址的概念1.2 URL的组成1.3 知识要点 2、HTTP协议的介绍2.1 HTTP协议的概念及作用2.2 HTTP协议的概念及作用2.3 浏览器访问Web服务器的过程 3、HTTP请求报文3.1 H…