网络编程 —— 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     10

int 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 8888

int 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); // 清0


	iRet = 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 8888

int 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 8888

int 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);

#endif

	while (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;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

nodejs+vue公益帮学网站的设计与实现-微信小程序-安卓-python-PHP-计算机毕业设计

在当今高度发达的信息中&#xff0c;信息管理改革已成为一种更加广泛和全面的趋势。为确保中国经济的持续发展&#xff0c; 如何用方便快捷的方式使管理者在广阔的数据海洋里面查询、存储、管理和共享有效的数据信息&#xff0c;对我们的学习&#xff0c;工作和生活具有重要的现…

创造者设计模式

Bike package com.jmj.pattern.builder.demo01;public class Bike {private String frame;//车架private String seat;//车座public String getFrame() {return frame;}public void setFrame(String frame) {this.frame frame;}public String getSeat() {return seat;}public…

Webpack Bundle Analyzer包分析器

当我们需要分析打包文件dist里哪些资源可以进一步优化时&#xff0c;就可以使用包分析器插件webpack-bundle-analyzer。NPM上的介绍是使用交互式可缩放树图可视化 webpack 输出文件的大小。 我的是vue2项目。 1、webpack-bundle-analyzer插件的安装 $ npm install --save-dev…

接口测试vs功能测试

接口测试和功能测试的区别&#xff1a; 本文主要分为两个部分&#xff1a; 第一部分&#xff1a;主要从问题出发&#xff0c;引入接口测试的相关内容并与前端测试进行简单对比&#xff0c;总结两者之前的区别与联系。但该部分只交代了怎么做和如何做&#xff1f;并没有解释为什…

Kyligence 入选 Gartner® 2023 客户之声报告,高分获评“卓越表现者”

近日&#xff0c;Gartner 发布了最新的《2023 分析和商业智能平台“客户之声”报告》(Voice of the Customer for Analytics and Business Intelligence Platforms, 2023, October 2023)。跬智信息&#xff08;Kyligence&#xff09;成功入选该报告&#xff0c;并凭借 4.7 分&a…

嵌入式养成计划-54----ARM--异常处理流程

一百三十五、异常处理流程 135.1 arm处理器工作模式 135.2 异常源和异常模式关系 135.2.1 异常源 异常源就是引发处理器进入相应异常模式 135.2.2 对应关系 异常模式异常源FIQ模式FIQ类型异常源引发处理器进入FIQ模式IRQ模式IRQ类型异常源引发处理器进入IRQ模式SVC模式上电…

opencv车牌识别<一>

目录 一、概述 二、ANPR简介 一、概述 本文将介绍创建自动车牌识别(Automatic Number Plate Recognition&#xff0c;ANPR)所需的步骤。对于不同的情形&#xff0c;实现自动车牌识别会用不同的方法和技术&#xff0c;例如&#xff0c;IR 摄像机、固定汽车位置、光照条件等…

spring cloud之配置中心

Config 统一配置中心(*) 1.简介 # 统一配置中心 - 官网:https://cloud.spring.io/spring-cloud-static/spring-cloud-config/2.2.3.RELEASE/reference/html/#_spring_cloud_config_server- config 分为 config server 和 config client。用来统一管理所有微服务的配置统一配置…

【Python 千题 —— 基础篇】欢迎光临

题目描述 题目描述 欢迎光临。为列表中的每个嘉宾打印欢迎光临语句。例如&#xff0c;有一份嘉宾列表 ["李二狗", "王子鸣"]&#xff0c;则需要根据嘉宾名单打印输出&#xff1a; 欢迎光临&#xff01;李二狗。 欢迎光临&#xff01;王子鸣。下面是一份…

基于JAX-WS的RESTful web服务返回通过JAXB注解生成的xml文档

基于JAX-WS编写的RESTful web服务&#xff0c;返回xml文档。这个xml文档可以基于JAXB注解的形式来生成&#xff0c;简化xml的生成。 例如&#xff0c;下面RegisterResponse 这个类使用了JAXB的注解&#xff1a; package com.thb.server.register;import jakarta.xml.bind.ann…

C语言--指针与数组--遍历数组的n种方式【详细】

一.一维数组名的含义 arr一般表示数组的其实地址&#xff08;除了两种例外&#xff09; 1.在定义数组的同一个函数中(不是形参),求sizeof(arr),求整个数组的字节数 2.在定义数组的同一个函数中(不是形参),&arr1,加整个数组的大小 (经常考试) 3.除上面以外,arr都表示数组的…

智能穿戴AR眼镜主板方案定制_MTK平台AR智能眼镜PCB板开发

AR智能眼镜&#xff0c;是采用了多种技术实现增强现实效果&#xff0c;是将虚拟信息和现实场景相结合的智能设备。 AR智能眼镜硬件上&#xff0c;包括多个传感器、显示装置和处理器等。其中&#xff0c;传感器用于捕捉用户的动作和环境信息&#xff0c;如摄像头、陀螺仪、加速…

【python】爬取酷狗音乐Top500排行榜【附源码】

一、导入必要的模块&#xff1a; 这篇博客将介绍如何使用Python编写一个爬虫程序&#xff0c;从斗鱼直播网站上获取图片信息并保存到本地。我们将使用requests模块发送HTTP请求和接收响应&#xff0c;以及os模块处理文件和目录操作。 如果出现模块报错 进入控制台输入&#xff…

Axure原型设计工具怎么样?有替代软件吗?

Axurerp是一种快速原型设计工具&#xff0c;可以制作高度互动的HTML原型。设计师不仅可以使用Axure绘制线框图和原型&#xff0c;还可以在Axurerp中完成一系列用户体验设计。在本文中&#xff0c;我们将根据用户体验设计师的真实经验&#xff0c;触发用户体验设计师的实际工作&…

(论文阅读30/100)Convolutional Pose Machines

30.文献阅读笔记CPMs 简介 题目 Convolutional Pose Machines 作者 Shih-En Wei, Varun Ramakrishna, Takeo Kanade, and Yaser Sheikh, CVPR, 2016. 原文链接 https://arxiv.org/pdf/1602.00134.pdf 关键词 Convolutional Pose Machines&#xff08;CPMs&#xff09;…

数据库管理-第116期 Oracle Exadata 06-ESS-下(202301114)

数据库管理-第116期 Oracle Exadata 06-ESS-下&#xff08;202301114&#xff09; 距离上一次正儿八经的技术分享又过了整整一周了&#xff0c;距离上一期Exadata专题文章也过了11天了&#xff0c;今天一鼓作气把ESS写完&#xff0c;毕竟明天又要飞北京了。 1 Smart Scan 其…

SpringCloud Alibaba(中):服务熔断降级-Sentinel

Sentinel Sentinel是阿里巴巴开源的分布式系统流量防卫防护组件&#xff0c;主要对分布式系统中的流量进行控制、熔断降级等保护操作。Sentinel的目标是成为互联网级别分布式系统的流量防卫防护组件&#xff0c;它与系统的各个部分集成&#xff0c;保护着系统的入口和出口。 …

【蓝桥杯选拔赛真题20】C++求正方形面积 第十二届蓝桥杯青少年创意编程大赛C++编程选拔赛真题解析

目录 C/C++求正方形面积 一、题目要求 1、编程实现 2、输入输出 二、算法分析

Hadoop3.3.4分布式安装

安装前提&#xff1a;已经配置好java环境&#xff0c;所有机器之间ssh的免密登录。 注意&#xff1a;下文中的flinkv1、flinkv2、flinkv3是三台服务器的别名 1.集群部署规划 注意&#xff1a;NameNode和SecondaryNameNode不要安装在同一台服务器 注意&#xff1a;ResourceMan…

软件测试/测试开发丨​利用人工智能ChatGPT批量生成测试数据

点此获取更多相关资料 简介 测试数据是指一组专注于为测试服务的数据&#xff0c;既可以作为功能的输入去验证输出&#xff0c;也可以去触发各类异常场景。 测试数据的设计尤为重要&#xff0c;等价类、边界值、正交法等测试用例设计方法都是为了更全面地设计对应的测试数据…