bitpie app国际版|c网络编程

作者: bitpie app国际版
2024-03-10 20:24:42

C语言网络编程-CSDN博客

>

C语言网络编程-CSDN博客

C语言网络编程

最新推荐文章于 2023-12-31 21:39:04 发布

酉酉囧

最新推荐文章于 2023-12-31 21:39:04 发布

阅读量1.9w

收藏

199

点赞数

43

分类专栏:

其他

文章标签:

c

socket

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

本文链接:https://blog.csdn.net/qq_41725312/article/details/90375742

版权

其他

专栏收录该内容

4 篇文章

1 订阅

订阅专栏

文章目录

套接字Linux下的套接字Windows下的套接字建立Socketbind() 函数connect() 函数linsten() 函数accept() 函数Linux 接受和发送数据Windos 接受和发送数据

示例WindowsLinux

参考

套接字

socket,套接字,它是计算机之间进行通信的一种约定或一种方式。通过 socket 这种约定,一台计算机可以接收其他计算机的数据,也可以向其他计算机发送数据。

Linux下的套接字

Linux中创建的文件都有一个 int 类型的编号,称为文件描述符(File Descriptor)。使用文件时,只要知道文件描述符就可以。socket 也被认为是文件的一种,和普通文件的操作没有区别

Windows下的套接字

WinSock(Windows Socket)编程依赖于系统提供的动态链接库(DLL),有两个版本:

较早的DLL是 wsock32.dll,大小为 28KB,对应的头文件为 winsock1.h;最新的DLL是 ws2_32.dll,大小为 69KB,对应的头文件为 winsock2.h。

加载ws2_32.dll

#pragma comment (lib, "ws2_32.lib")

WSAStartup()

使用DLL之前,还需要调用 WSAStartup() 函数进行初始化,以指明 WinSock 规范的版本

int WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData);

wVersionRequested 为 WinSock 规范的版本号,低字节为主版本号,高字节为副版本号(修正版本号)lpWSAData 为指向 WSAData 结构体的指针。

eg:

WSADATA wsaData;

WSAStartup(MAKEWORD(2, 2), &wsaData);

建立Socket

Linux

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

af ,地址族(Address Family),常用AF_INET(IPv4) 和 AF_INET6(IPv6)。type ,数据传输方式,常用的有 SOCK_STREAM(面向连接)和 SOCK_DGRAM(无连接)protocol 表示传输协议,常用的有 IPPROTO_TCP(TCP协议) 和 IPPTOTO_UDP(UDP协议)

1.TCP socket

int tcp_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

2.UDP socket

int udp_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);

Windows

SOCKET sock = socket(AF_INET, SOCK_STREAM, 0); //创建TCP套接字

bind() 函数

将套接字与特定的IP地址和端口绑定起来

int bind(int sock, struct sockaddr *addr, socklen_t addrlen); //Linux

int bind(SOCKET sock, const struct sockaddr *addr, int addrlen); //Windows

示例

//创建套接字

int serv_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

//创建sockaddr_in结构体变量

struct sockaddr_in serv_addr;

memset(&serv_addr, 0, sizeof(serv_addr)); //每个字节都用0填充

serv_addr.sin_family = AF_INET; //使用IPv4地址

serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); //具体的IP地址

serv_addr.sin_port = htons(1234); //端口

//将套接字和IP、端口绑定

bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));

1、sockaddr_in 结构体

struct sockaddr_in{

sa_family_t sin_family; //地址族(Address Family),也就是地址类型

uint16_t sin_port; //16位的端口号

struct in_addr sin_addr; //32位IP地址

char sin_zero[8]; //不使用,一般用0填充

};

sin_family 和 socket() 的第一个参数的含义相同,取值也要保持一致。 sin_prot 为端口号。需要用 htons() 函数转换 sin_addr 是 struct in_addr 结构体类型的变量 in_addr 结构体 struct in_addr{

in_addr_t s_addr; //32位的IP地址

};

需要inet_addr()转换 serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");

2、sockaddr

bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));

bind() 第二个参数的类型为 sockaddr,而代码中却使用 sockaddr_in,然后再强制转换为 sockaddr,这是为什么呢?

sockaddr 结构体的定义如下:

struct sockaddr{

sa_family_t sin_family; //地址族(Address Family),也就是地址类型

char sa_data[14]; //IP地址和端口号

};

下图是 sockaddr 与 sockaddr_in 的对比(括号中的数字表示所占用的字节数):

sockaddr 和 sockaddr_in 的长度相同,都是16字节,只是将IP地址和端口号合并到一起,用一个成员 sa_data 表示。要想给 sa_data 赋值,必须同时指明IP地址和端口号,例如”127.0.0.1:80“,遗憾的是,没有相关函数将这个字符串转换成需要的形式,也就很难给 sockaddr 类型的变量赋值,所以使用 sockaddr_in 来代替。这两个结构体的长度相同,强制转换类型时不会丢失字节,也没有多余的字节。

connect() 函数

建立连接

与bind类似

int connect(int sock, struct sockaddr *serv_addr, socklen_t addrlen); //Linux

int connect(SOCKET sock, const struct sockaddr *serv_addr, int addrlen); //Windows

linsten() 函数

套接字进入被动监听状态

int listen(int sock, int backlog); //Linux

int listen(SOCKET sock, int backlog); //Windows

sock 需要进入监听状态的套接字backlog 请求队列的最大长度

accept() 函数

套接字处于监听状态时,接收客户端请求,返回新的套接字

int accept(int sock, struct sockaddr *addr, socklen_t *addrlen); //Linux

SOCKET accept(SOCKET sock, struct sockaddr *addr, int *addrlen); //Windows

sock 为服务器端套接字addr 为 sockaddr_in 结构体变量addrlen 为参数 addr 的长度,可由 sizeof() 求得

Linux 接受和发送数据

write()

写入数据

ssize_t write(int fd, const void *buf, size_t nbytes);

fd 为要写入的文件的描述符buf 为要写入的数据的缓冲区地址nbytes 为要写入的数据的字节数。

read()

读取数据

ssize_t read(int fd, void *buf, size_t nbytes);

fd 为要读取的文件的描述符buf 为要接收数据的缓冲区地址nbytes 为要读取的数据的字节数。

Windos 接受和发送数据

send()

发送数据

int send(SOCKET sock, const char *buf, int len, int flags);

sock 为要发送数据的套接字buf 为要发送的数据的缓冲区地址len 为要发送的数据的字节数flags 为发送数据时的选项,一般设置为 0 或 NULL

recv()

接受数据

int recv(SOCKET sock, char *buf, int len, int flags);

同上

示例

Windows

server

#include

#include

#pragma comment (lib, "ws2_32.lib") //加载 ws2_32.dll

int main(){

//初始化 DLL

WSADATA wsaData;

WSAStartup(MAKEWORD(2, 2), &wsaData);

//创建套接字 PF_INET:IPv4

SOCKET servSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);

//绑定套接字

sockaddr_in sockAddr;

memset(&sockAddr, 0, sizeof(sockAddr)); //每个字节都用0填充

sockAddr.sin_family = PF_INET; //使用IPv4地址

sockAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); //具体的IP地址

sockAddr.sin_port = htons(1234); //端口

bind(servSock, (SOCKADDR*)&sockAddr, sizeof(SOCKADDR));

//进入监听状态

listen(servSock, 20);

//接收客户端请求

SOCKADDR clntAddr;

int nSize = sizeof(SOCKADDR);

SOCKET clntSock = accept(servSock, (SOCKADDR*)&clntAddr, &nSize);

//向客户端发送数据

char *str = "Hello World!";

send(clntSock, str, strlen(str)+sizeof(char), NULL);

//关闭套接字

closesocket(clntSock);

closesocket(servSock);

//终止 DLL 的使用

WSACleanup();

return 0;

}

client

#include

#include

#include

#pragma comment(lib, "ws2_32.lib")

//加载 ws2_32.dll

int main(){

//初始化DLL

WSADATA wsaData;

WSAStartup(MAKEWORD(2, 2), &wsaData);

//创建套接字

SOCKET sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);

//向服务器发起请求

sockaddr_in sockAddr;

memset(&sockAddr, 0, sizeof(sockAddr)); //每个字节都用0填充

sockAddr.sin_family = PF_INET;

sockAddr.sin_addr.s_addr = inet_addr("127.0.0.1");

sockAddr.sin_port = htons(1234);

connect(sock, (SOCKADDR*)&sockAddr, sizeof(SOCKADDR));

//接收服务器传回的数据

char szBuffer[MAXBYTE] = {0};

recv(sock, szBuffer, MAXBYTE, NULL);

//输出接收到的数据

printf("Message form server: %s\n", szBuffer);

//关闭套接字

closesocket(sock);

//终止使用 DLL

WSACleanup();

system("pause");

return 0;

Linux

服务器端代码 server.cpp

#include

#include

#include

#include

#include

#include

#include

int main(){

//创建套接字

int serv_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

//将套接字和IP、端口绑定

struct sockaddr_in serv_addr;

memset(&serv_addr, 0, sizeof(serv_addr)); //每个字节都用0填充

serv_addr.sin_family = AF_INET; //使用IPv4地址

serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); //具体的IP地址

serv_addr.sin_port = htons(1234); //端口

bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));

//进入监听状态,等待用户发起请求

listen(serv_sock, 20);

//接收客户端请求

struct sockaddr_in clnt_addr;

socklen_t clnt_addr_size = sizeof(clnt_addr);

int clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_addr_size);

//向客户端发送数据

char str[] = "Hello World!";

write(clnt_sock, str, sizeof(str));

//关闭套接字

close(clnt_sock);

close(serv_sock);

return 0;

}

客户端代码 client.cpp:

#include

#include

#include

#include

#include

#include

int main(){

//创建套接字

int sock = socket(AF_INET, SOCK_STREAM, 0);

//向服务器(特定的IP和端口)发起请求

struct sockaddr_in serv_addr;

memset(&serv_addr, 0, sizeof(serv_addr)); //每个字节都用0填充

serv_addr.sin_family = AF_INET; //使用IPv4地址

serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); //具体的IP地址

serv_addr.sin_port = htons(1234); //端口

connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));

//读取服务器传回的数据

char buffer[40];

read(sock, buffer, sizeof(buffer)-1);

printf("Message form server: %s\n", buffer);

//关闭套接字

close(sock);

return 0;

}

参考

C语言网络编程_C语言中文网

优惠劵

酉酉囧

关注

关注

43

点赞

199

收藏

觉得还不错?

一键收藏

知道了

4

评论

C语言网络编程

文章目录套接字Windows下的套接字Linux下的套接字Socketbind() 函数connect() 函数linsten() 函数accept() 函数Linux 接受和发送数据Windos 接受和发送数据示例WindowsLinux参考套接字socket,套接字,它是计算机之间进行通信的一种约定或一种方式。通过 socket 这种约定,一台计算机可以接收其他计算机的数据,也可以向其他...

复制链接

扫一扫

专栏目录

C语言网络编程——课程设计文档

03-21

NULL

博文链接:https://wanghailiang.iteye.com/blog/930515

c语言网络编程-标准步骤(改进版)

09-04

主要介绍了c语言网络编程-标准步骤的改进说明,需要的朋友可以参考下

4 条评论

您还未登录,请先

登录

后发表或查看评论

C语言基础知识(5):TCP网络编程

weixin_55238862的博客

12-31

934

TCP 是面向连接的、可靠的流协议。流就是指不间断的数据结构,当应用程序采用 TCP 发送消息时,虽然可以保证发送的顺序,但还是犹如没有任何间隔的数据流发送给接收端。TCP 为提供可靠性传输,实行“顺序控制”或“重发控制”机制。此外还具备“流控制(流量控制)”、“拥塞控制”、提高网络利用率等众多功能。

简析Windows C语言网络编程技术与方法.pdf

09-19

简析Windows C语言网络编程技术与方法.pdf

ftp传输---c语言网络编程

09-27

自己写的c语言通过网络传输文件,有获取、发送、显示目录、 删除。可以自己增加功能。。。。。。。。。。。。。。。。。。。。。。。

c语言网络编程-标准步骤(比较简单)

01-21

c语言网络编程-标准步骤,真的很简单啊

server.c

代码如下:#include #include #include #include #include #include #include #include #define PORT 4444#define BACKLOG 5int main(int argc, char *argv[]) {    int sock_fd, new_fd;    stru

C语言网络编程——基础

Stars____的博客

04-28

7483

OSI七层参考模型

是理想化的并没有完全实现的模型。

应用层

提供响应的应用服务

表示层

数据的表示和加密

会话层

建立会话关系

传输层

通过传输协议传输数据

网络层

实现跨子网通信,路由转发,维护路由表。

数据链路层

实现以太网内数据帧的转发

物理层

按照一定的传输规则传输电信号。

TCP/IP 四层模型

详细介绍见https://blog.csdn.net/Stars____/article/details/108694074

SCTP协议:TCP的升级版

TCP/IP 网络编程

unix域套接字:用于

C语言之网络编程(必背知识点)

qq_52049228的博客

05-27

3991

提供了一个面向连接、可靠的数据传输服务,数据无差错、无重复的发送且按发送顺序接收。内设置流量控制,避免数据流淹没慢的接收方。数据被看作是字节流,无长度限制。

什么是网络编程,C 语言中如何进行网络编程?C 语言中如何进行数据库编程?

fengyege的博客

07-23

617

网络编程是指使用计算机网络进行数据传输和通信的编程技术。它涉及到服务器和客户端之间的数据交换和通信。在C语言中,网络编程可以通过使用套接字(socket)库来实现。套接字是一种用于网络通信的抽象,它提供了一组函数和数据结构,可以在应用程序之间进行网络通信。以下是C语言中进行网络编程的基本步骤:创建套接字:使用socket()函数创建一个套接字。

C语言动态获取设备的网络接口名称和状态以及对应的IP地址

coderma的博客

07-13

839

C语言动态获取设备的网络接口名称和状态以及对应的IP地址

C语言网络编程快速入门

01-11

C语言网络编程快速入门

C语言的学习,一般的方式是:先学C,然后是C++,

最好还要有汇编语言和微机原理基础,然后才是Visual

C++。这样的方式,对学习者来说,要花费很多时间和

精力。而在学校教学中,也就没有时间深入学习Win—

dows编程的实用技术了。

其实,具有了C语言基础后,再有一些基本的C++

类的概念,就可以直接学习Windows C编程了。

linux C语言 网络编程教程及源码

05-12

linux C语言 网络编程教程及源码

一、网络应用层编程

1、Linux网络编程01——网络协议入门

2、Linux网络编程02——无连接和面向连接的区别

3、Linux网络编程03——字节序和地址转换

4、Linux网络编程04——套接字

5、Linux网络编程05——C/S与B/S架构的区别

6、Linux网络编程06——UDP协议编程

7、Linux网络编程07——广播

8、Linux网络编程08——多播

9、Linux网络编程09——TCP编程之客户端

10、Linux网络编程10——TCP编程之服务器

11、Linux网络编程11——tcp、udp迭代服务器

12、Linux网络编程12——tcp三次握手、四次挥手

13、Linux网络编程13——connect()、listen()和accept()三者之间的关系

14、Linux网络编程14——I/O复用之select详解

15、Linux网络编程15——I/O复用之poll详解

16、Linux网络编程16——I/O复用之epoll详解

17、Linux网络编程17——tcp并发服务器(多进程)

18、Linux网络编程18——tcp并发服务器(多线程)

19、Linux网络编程——tcp高效并发服务器(select实现)

20、Linux网络编程——tcp高效并发服务器(poll实现)

21、Linux网络编程——tcp高效并发服务器(epoll实现)

二、网络底层编程(黑客模式)

1、Linux网络编程1——啥叫原始套接字

2、Linux网络编程2——原始套接字编程

3、Linux网络编程3——原始套接字实例:MAC头分析

4、Linux网络编程4——原始套接字实例:MAC地址扫描器

5、Linux网络编程5——IP数据报格式详解

6、Linux网络编程6——TCP、UDP数据包格式详解

7、Linux网络编程7——原始套接字实例:发送UDP数据包

8、Linux网络编程8——libpcap详解

9、Linux网络编程9——libnet详解

windows下的C语言网络编程.pdf

03-21

windows下的C语言网络编程.pdfwindows下的C语言网络编程.pdfwindows下的C语言网络编程.pdfwindows下的C语言网络编程.pdfwindows下的C语言网络编程.pdf

K8s 很难么?带你从头到尾捋一遍,不信你学不会

民工哥的博客

02-23

8559

点击关注公众号,回复“1024”获取2TB学习资源!为什么要学习 Kubernetes?虽然 Docker 已经很强大了,但是在实际使用上还是有诸多不便,比如集群管理、资源调度、文件管理等...

10天智能锁项目实战第1天(了解单片机STM32F401RET6和C语言基础)

北豼不太皮的博客

02-21

2898

10天智能锁项目实战第1天(了解单片机STM32F401RET6和C语言基础)一、学习目标二、了解单片机STM32F401RET6三、C语言基础

一、学习目标

二、了解单片机STM32F401RET6

4、STM32F401RE特征

三、C语言基础

1.数据类型

常用2的次方:

2^7 = 128

2^8 = 256

2^15 = 32768

2^16= 65536

51单片机常见的数据类型:

char: 占内存1字节 取值范围:-128~127 -2^7 ~ 2

Android开发(1) | Fragment 的应用——新闻应用

Jormungand_V的博客

02-21

3355

文章目录

news_item.xml:

xmlns:android="http://schemas.android.com/apk/res/android"

android:id="@+id/news_title"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:lines="1"

android:ellipsize="

系统学习 TypeScript(四)——变量声明的初步学习

编程三昧

02-25

1349

认识了 TypeScript 中的基础类型,接下来当然是变量声明的相关学习了,我在这里记录一下我学习过程中的一些总结。

清除浮动的五种方法

weixin_52212950的博客

02-22

1913

为什么要清除浮动?因为往往浮动后的子元素因为脱离了标准流,不能自动撑起父元素的高度,所以会对后续布局产生影响,对此清除浮动不如理解为清除浮动产生的影响更为合理。

例如:我们设置了两个盒子如图所示,粉色为父盒子,只有宽度没有高度,蓝色盒子有宽有高,粉色盒子的高由蓝盒子的高度撑开。

但是给蓝色的子盒子设置了左浮动后,脱离了标准流,无法再撑开粉盒子,可以看到粉盒子高度变成了0;

清除浮动有五种方法:

直接设置父元素的高度

额外标签法

单伪元素法

双伪元素法

ove.

c语言网络编程如何组帧

最新发布

01-19

C语言网络编程中,组帧是将数据按照一定的格式打包成帧的过程。组帧的目的是为了在网络传输中能够准确地识别数据的起始和结束,并且能够正确地解析数据。

在C语言网络编程中,组帧通常包括以下步骤:

1. 定义帧格式:首先需要确定数据在网络中的传输格式,即帧的起始标志、数据长度、数据内容和校验码等信息。

2. 封装数据:根据定义的帧格式,将数据按照格式进行封装,将数据按照帧的格式组织成一个完整的帧。

3. 加入校验:为了保证数据的完整性和正确性,通常在帧中加入校验码,比如CRC校验,用于检测并纠正数据在传输中的错误。

4. 发送帧:封装完成的帧通过网络传输给接收端,接收端则需要进行帧的解析和处理。

总之,在C语言网络编程中,组帧是非常重要的一步,通过合理的组帧可以保证数据在网络中的正确传输,提高数据的可靠性和稳定性。

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

非常没帮助

没帮助

一般

有帮助

非常有帮助

提交

酉酉囧

CSDN认证博客专家

CSDN认证企业博客

码龄6年

暂无认证

41

原创

5万+

周排名

168万+

总排名

15万+

访问

等级

1649

积分

63

粉丝

127

获赞

32

评论

578

收藏

私信

关注

热门文章

仿射密码解析与实例

26669

C语言网络编程

19850

Oh My Zsh 强大炫酷的Shell

13688

Bugku web 管理员系统 write up

13245

yersinia工具的使用(vlan跳跃,stp攻击等)

10436

分类专栏

Crypto

2篇

write up

4篇

环境搭建

5篇

PHP审计

6篇

MySQL

2篇

Web

5篇

网络

4篇

Pyhton

12篇

其他

4篇

二进制安全

1篇

最新评论

macOS 12 pyenv 和 pyenv-virtualenv 安装和使用

Tobyllllllba:

你好想请问一下,没有配置shell环境可以直接下载python吗?我输入这个直接卡住了,不知道是不是在下载

tobylin@Tobys-Macbook ~ % pyenv install 3.8.10

python-build: use openssl from homebrew

python-build: use readline from homebrew

Downloading Python-3.8.10.tar.xz...

-> https://www.python.org/ftp/python/3.8.10/Python-3.8.10.tar.xz

网络嗅探dsniff套件的使用

what d:

请问作者大大urlsnarf可以嗅探手机吗?

yersinia工具的使用(vlan跳跃,stp攻击等)

今天也要加油^0^~:

您好 ,请问我的dhcp 地址耗尽攻击和dhcp欺骗不能同时运行,是内存不够,还是软件本身不兼容呢?

Python 协议攻击脚本(七): DHCP攻击

findriver:

只能在linux下用吗?Windows下没有效果

Python 协议攻击脚本(七): DHCP攻击

XINGDAREN:

用什么抓包呀

您愿意向朋友推荐“博客详情页”吗?

强烈不推荐

不推荐

一般般

推荐

强烈推荐

提交

最新文章

Swift 学习笔记

Spring heapdump 敏感信息查找

Python 打印菜单

2022年4篇

2020年2篇

2019年20篇

2018年17篇

目录

目录

分类专栏

Crypto

2篇

write up

4篇

环境搭建

5篇

PHP审计

6篇

MySQL

2篇

Web

5篇

网络

4篇

Pyhton

12篇

其他

4篇

二进制安全

1篇

目录

评论 4

被折叠的  条评论

为什么被折叠?

到【灌水乐园】发言

查看更多评论

添加红包

祝福语

请填写红包祝福语或标题

红包数量

红包个数最小为10个

红包总金额

红包金额最低5元

余额支付

当前余额3.43元

前往充值 >

需支付:10.00元

取消

确定

下一步

知道了

成就一亿技术人!

领取后你会自动成为博主和红包主的粉丝

规则

hope_wisdom 发出的红包

实付元

使用余额支付

点击重新获取

扫码支付

钱包余额

0

抵扣说明:

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

余额充值

【socket】C语言的Socket网络编程 - bdy - 博客园

【socket】C语言的Socket网络编程 - bdy - 博客园

会员

周边

新闻

博问

AI培训

云市场

所有博客

当前博客

我的博客

我的园子

账号设置

简洁模式 ...

退出登录

注册

登录

UESTC

【socket】C语言的Socket网络编程

目录

Socket网络编程

1、网络知识

网络中进程之间如何通信?

什么是Socket?

socket一词的起源

 怎么理解端口?

 怎么理解socket ?

2. 客户/服务器模式

2.1 服务器端:

2.2 客户端:

4. 套接字函数

4.1 创建套接字──socket()

4.2 指定本地地址──bind() 

4.3 建立套接字连接──connect()与accept()

4.4 监听连接──listen() 

4.5 数据传输──send()与recv() 

4.6 关闭套接字──close

4.6 recv和read|send和write的区别

编程实例

Linux下C语言的Socket编程例子(多线程)

Windows下C语言的Socket编程例子

【Socket】有很多BUG,测试人员要注意。

网络字节序与主机字节序

3.1、socket()函数

3.2、bind()函数

3.3、listen()、connect()函数

3.4、accept()函数

3.5、read()、write()等函数

3.6、close()函数

4、socket中TCP的三次握手建立连接详解

5、socket中TCP的四次握手释放连接详解

 6、一个例子(实践一下)

7、动动手

Socket网络编程

1、网络知识

网络中进程之间如何通信?

本地的进程间通信(IPC)有很多种方式,但可以总结为下面4类:

消息传递(管道、FIFO、消息队列) 同步(互斥量、条件变量、读写锁、文件和写记录锁、信号量) 共享内存(匿名的和具名的) 远程过程调用(Solaris门和Sun RPC)

但这些都不是本文的主题!我们要讨论的是网络中进程之间如何通信?首要解决的问题是如何唯一标识一个进程,否则通信无从谈起!在本地可以通过进程PID来唯一标识一个进程,但是在网络中这是行不通的。其实TCP/IP协议族已经帮我们解决了这个问题,网络层的“ip地址”可以唯一标识网络中的主机,而传输层的“协议+端口”可以唯一标识主机中的应用程序(进程)。这样利用三元组(ip地址,协议,端口)就可以标识网络的进程了,网络中的进程通信就可以利用这个标志与其它进程进行交互。

使用TCP/IP协议的应用程序通常采用应用编程接口:UNIX  BSD的套接字(socket)和UNIX System V的TLI(已经被淘汰),来实现网络进程之间的通信。就目前而言,几乎所有的应用程序都是采用socket,而现在又是网络时代,网络中进程通信是无处不在,这就是我为什么说“一切皆socket”。

什么是Socket?

上面我们已经知道网络中的进程是通过socket来通信的,那什么是socket呢?socket起源于Unix,而Unix/Linux基本哲学之一就是“一切皆文件”,都可以用“打开open –> 读写write/read –> 关闭close”模式来操作。我的理解就是Socket就是该模式的一个实现,socket即是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO、打开、关闭),这些函数我们在后面进行介绍。

socket一词的起源

在组网领域的首次使用是在1970年2月12日发布的文献IETF RFC33中发现的,撰写者为Stephen Carr、Steve Crocker和Vint Cerf。根据美国计算机历史博物馆的记载,Croker写道:“命名空间的元素都可称为套接字接口。一个套接字接口构成一个连接的一端,而一个连接可完全由一对套接字接口规定。”计算机历史博物馆补充道:“这比BSD的套接字接口定义早了大约12年。”

 怎么理解端口?

我们平时说的端口一般都是指逻辑端口,比如浏览器用的 80 端口,FTP 工具用的 21 端口。由于网络工具众多,于是对网络端口做了编号,从 0 到 65535。

其中 0 - 1023 是公认的端口号,就是已经被一些知名的软件给占用了。留给我们程序里面使用的是 1024 - 65535。

程序 socket通过绑定操作占领x端口,接下来其他程序将不能使用 x端口。一旦 x端口收到数据,系统都会转发给该程序,所以不会出现微信好友发送的数据,被QQ给收到了。可以简单地理解成,操作系统通过端口号,把不同的应用程序区分开。 作者:linux 链接:https://www.zhihu.com/question/535823141/answer/2538570947

 怎么理解socket ?

socket 套接字 莫名其妙,难道真是下面图片的而来?

套接字(socket)属于糟糕的翻译,因为它太生僻。“套接”生活中用得少,加个“字”,成了套接字。当你学了socket以后,你还是很难将名字与它的意思联系起来。香港翻译成:網路插座 感觉贴近一些

2. 客户/服务器模式

在TCP/IP网络应用中,通信的两个进程间相互作用的主要模式是客户/服务器(Client/Server, C/S)模式,即客户向服务器发出服务请求,服务器接收到请求后,提供相应的服务。

客户/服务器模式的建立基于以下两点: (1)首先,建立网络的起因是网络中软硬件资源、运算能力和信息不均等,需要共享,从而造就拥有众多资源的主机提供服务,资源较少的客户请求服务这一非对等作用。 (2)其次,网间进程通信完全是异步的,相互通信的进程间既不存在父子关系,又不共享内存缓冲区,因此需要一种机制为希望通信的进程间建立联系,为二者的数据交换提供同步,这就是基于客户/服务器模式的TCP/IP。  

2.1 服务器端:

其过程是首先服务器方要先启动,并根据请求提供相应服务: (1)打开一通信通道并告知本地主机,它愿意在某一公认地址上的某端口(如FTP的端口可能为21)接收客户请求; (2)等待客户请求到达该端口; (3)接收到客户端的服务请求时,处理该请求并发送应答信号。接收到并发服务请求,要激活一新进程来处理这个客户请求(如UNIX系统中用fork、exec)。新进程处理此客户请求,并不需要对其它请求作出应答。服务完成后,关闭此新进程与客户的通信链路,并终止。 (4)返回第(2)步,等待另一客户请求。 (5)关闭服务器

2.2 客户端:

(1)打开一通信通道,并连接到服务器所在主机的特定端口; (2)向服务器发服务请求报文,等待并接收应答;继续提出请求...... (3)请求结束后关闭通信通道并终止。

从上面所描述过程可知: (1)客户与服务器进程的作用是非对称的,因此代码不同。 (2)服务器进程一般是先启动的。只要系统运行,该服务进程一直存在,直到正常或强迫终止。 3. 基本TCP套接字编程 基于 TCP 的套接字编程的所有客户端和服务器端都是从调用socket 开始,它返回一个套接字描述符。客户端随后调用connect 函数,服务器端则调用 bind、listen 和accept 函数。套接字通常使用标准的close 函数关闭,但是也可以使用 shutdown 函数关闭套接字。

下图为TCP套接字编程流程图:

4. 套接字函数

4.1 创建套接字──socket()

应用程序在使用套接字前,首先必须拥有一个套接字,系统调用socket()向应用程序提供创建套接字的手段,

其调用格式如下: SOCKET PASCAL FAR socket(int af, int type, int protocol);

该调用要接收三个参数:af、type、protocol。参数af指定通信发生的区域:AF_UNIX、AF_INET、AF_NS等,而DOS、WINDOWS中仅支持AF_INET,它是网际网区域。因此,地址族与协议族相同。参数type 描述要建立的套接字的类型。

这里分三种: (1)一是TCP流式套接字(SOCK_STREAM)提供了一个面向连接、可靠的数据传输服务,数据无差错、无重复地发送,且按发送顺序接收。内设流量控制,避免数据流超限;数据被看作是字节流,无长度限制。文件传送协议(FTP)即使用流式套接字。 (2)二是数据报式套接字(SOCK_DGRAM)提供了一个无连接服务。数据包以独立包形式被发送,不提供无错保证,数据可能丢失或重复,并且接收顺序混乱。网络文件系统(NFS)使用数据报式套接字。 (3)三是原始式套接字(SOCK_RAW)该接口允许对较低层协议,如IP、ICMP直接访问。常用于检验新的协议实现或访问现有服务中配置的新设备。 参数protocol说明该套接字使用的特定协议,如果调用者不希望特别指定使用的协议,则置为0,使用默认的连接模式。根据这三个参数建立一个套接字,并将相应的资源分配给它,同时返回一个整型套接字号。因此,socket()系统调用实际上指定了相关五元组中的“协议”这一元。

4.2 指定本地地址──bind() 

当一个套接字用socket()创建后,存在一个名字空间(地址族),但它没有被命名。bind()将套接字地址(包括本地主机地址和本地端口地址)与所创建的套接字号联系起来,即将名字赋予套接字,以指定本地半相关。

其调用格式如下: int PASCAL FAR bind(SOCKET s, const struct sockaddr FAR * name, int namelen);

参数s是由socket()调用返回的并且未作连接的套接字描述符(套接字号)。参数name 是赋给套接字s的本地地址(名字),其长度可变,结构随通信域的不同而不同。namelen表明了name的长度。如果没有错误发生,bind()返回0。否则返回SOCKET_ERROR。

4.3 建立套接字连接──connect()与accept()

这两个系统调用用于完成一个完整相关的建立,其中connect()用于建立连接。accept()用于使服务器等待来自某客户进程的实际连接。

connect()的调用格式如下: int PASCAL FAR connect(SOCKET s, const struct sockaddr FAR * name, int namelen);

参数s是欲建立连接的本地套接字描述符。参数name指出说明对方套接字地址结构的指针。对方套接字地址长度由namelen说明。 如果没有错误发生,connect()返回0。否则返回值SOCKET_ERROR。在面向连接的协议中,该调用导致本地系统和外部系统之间连接实际建立。 由于地址族总被包含在套接字地址结构的前两个字节中,并通过socket()调用与某个协议族相关。因此bind()和connect()无须协议作为参数。

accept()的调用格式如下: SOCKET PASCAL FAR accept(SOCKET s, struct sockaddr FAR* addr, int FAR* addrlen);

参数s为本地套接字描述符,在用做accept()调用的参数前应该先调用过listen()。addr 指向客户方套接字地址结构的指针,用来接收连接实体的地址。addr的确切格式由套接字创建时建立的地址族决定。addrlen 为客户方套接字地址的长度(字节数)。如果没有错误发生,accept()返回一个SOCKET类型的值,表示接收到的套接字的描述符。否则返回值INVALID_SOCKET。

accept()用于面向连接服务器。参数addr和addrlen存放客户方的地址信息。调用前,参数addr 指向一个初始值为空的地址结构,而addrlen 的初始值为0;调用accept()后,服务器等待从编号为s的套接字上接受客户连接请求,而连接请求是由客户方的connect()调用发出的。当有连接请求到达时,accept()调用将请求连接队列上的第一个客户方套接字地址及长度放入addr 和addrlen,并创建一个与s有相同特性的新套接字号。新的套接字可用于处理服务器并发请求。

四个套接字系统调用,socket()、bind()、connect()、accept(),可以完成一个完全五元相关的建立。socket()指定五元组中的协议元,它的用法与是否为客户或服务器、是否面向连接无关。bind()指定五元组中的本地二元,即本地主机地址和端口号,其用法与是否面向连接有关:在服务器方,无论是否面向连接,均要调用bind(),若采用面向连接,则可以不调用bind(),而通过connect()自动完成。若采用无连接,客户方必须使用bind()以获得一个唯一的地址。

4.4 监听连接──listen() 

此调用用于面向连接服务器,表明它愿意接收连接。listen()需在accept()之前调用,

其调用格式如下: int PASCAL FAR listen(SOCKET s, int backlog);

参数s标识一个本地已建立、尚未连接的套接字号,服务器愿意从它上面接收请求。backlog表示请求连接队列的最大长度,用于限制排队请求的个数,目前允许的最大值为5。如果没有错误发生,listen()返回0。否则它返回SOCKET_ERROR。 listen()在执行调用过程中可为没有调用过bind()的套接字s完成所必须的连接,并建立长度为backlog的请求连接队列。 调用listen()是服务器接收一个连接请求的四个步骤中的第三步。它在调用socket()分配一个流套接字,且调用bind()给s赋于一个名字之后调用,而且一定要在accept()之前调用。

4.5 数据传输──send()与recv() 

当一个连接建立以后,就可以传输数据了。常用的系统调用有send()和recv()。 send()调用用于s指定的已连接的数据报或流套接字上发送输出数据,格式如下:

int PASCAL FAR send(SOCKET s, const char FAR *buf, int len, int flags);

参数s为已连接的本地套接字描述符。buf 指向存有发送数据的缓冲区的指针,其长度由len 指定。flags 指定传输控制方式,如是否发送带外数据等。如果没有错误发生,send()返回总共发送的字节数。否则它返回SOCKET_ERROR。

recv()调用用于s指定的已连接的数据报或流套接字上接收输入数据,格式如下:

int PASCAL FAR recv(SOCKET s, char FAR *buf, int len, int flags);

参数s 为已连接的套接字描述符。buf指向接收输入数据缓冲区的指针,其长度由len 指定。flags 指定传输控制方式,如是否接收带外数据等。如果没有错误发生,recv()返回总共接收的字节数。如果连接被关闭,返回0。否则它返回SOCKET_ERROR。

4.6 关闭套接字──close

close()关闭套接字s,并释放分配给该套接字的资源;如果s涉及一个打开的TCP连接,则该连接被释放。

4.6 recv和read|send和write的区别

int recv(int sockfd,void *buf,int len,int flags)  recv 比read 的功能强大点,体现在recv提供的flags参数上, recv最终的实现还是要调用read。 recv和read都可以操作阻塞或非阻塞,阻塞非阻塞与recv和read没关系,它是socket的属性,函数fcntl可以设置。

read和recv等函数的区别 | 学步园

编程实例

Linux下C语言的Socket编程例子(多线程)

2018-10-02 12:50:42

考虑到了关闭连接退出机制,多线程编程,以及线程参数的传递,值得学习

服务端

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define MAXCONN 2

#define ERRORCODE -1

#define BUFFSIZE 1024

int count_connect = 0;

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

struct pthread_socket

{

int socket_d;

pthread_t thrd;

};

static void *thread_send(void *arg)

{

char buf[BUFFSIZE];

int sd = *(int *) arg;

memset(buf, 0, sizeof(buf));

strcpy(buf, "hello,welcome to you! \n");

if (send(sd, buf, strlen(buf), 0) == -1)

{

printf("send error:%s \n", strerror(errno));

return NULL;

}

while (1)

{

memset(buf, 0, sizeof(buf));

read(STDIN_FILENO, buf, sizeof(buf));

if (send(sd, buf, strlen(buf), 0) == -1)

{

printf("send error:%s \n", strerror(errno));

break;

}

}

return NULL;

}

static void* thread_recv(void *arg)

{

char buf[BUFFSIZE];

struct pthread_socket *pt = (struct pthread_socket *) arg;

int sd = pt->socket_d;

pthread_t thrd = pt->thrd;

while (1)

{

memset(buf, 0, sizeof(buf));

int rv = recv(sd, buf, sizeof(buf), 0); //是阻塞的

if (rv < 0)

{

printf("recv error:%s \n", strerror(errno));

break;

}

if (rv == 0) // 这种情况说明client已经关闭socket连接

{

break;

}

printf("%s", buf); //输出接受到内容

}

pthread_cancel(thrd);

pthread_mutex_lock(&mutex);

count_connect--;

pthread_mutex_unlock(&mutex);

close(sd);

return NULL;

}

static int create_listen(int port)

{

int listen_st;

struct sockaddr_in sockaddr; //定义IP地址结构

int on = 1;

listen_st = socket(AF_INET, SOCK_STREAM, 0); //初始化socket

if (listen_st == -1)

{

printf("socket create error:%s \n", strerror(errno));

return ERRORCODE;

}

if (setsockopt(listen_st, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) //设置ip地址可重用

{

printf("setsockopt error:%s \n", strerror(errno));

return ERRORCODE;

}

sockaddr.sin_port = htons(port); //指定一个端口号并将hosts字节型传化成Inet型字节型(大端或或者小端问题)

sockaddr.sin_family = AF_INET; //设置结构类型为TCP/IP

sockaddr.sin_addr.s_addr = htonl(INADDR_ANY); //服务端是等待别人来连,不需要找谁的ip

//这里写一个长量INADDR_ANY表示server上所有ip,这个一个server可能有多个ip地址,因为可能有多块网卡

if (bind(listen_st, (struct sockaddr *) &sockaddr, sizeof(sockaddr)) == -1)

{

printf("bind error:%s \n", strerror(errno));

return ERRORCODE;

}

if (listen(listen_st, 5) == -1) // 服务端开始监听

{

printf("listen error:%s \n", strerror(errno));

return ERRORCODE;

}

return listen_st;

}

int accept_socket(int listen_st)

{

int accept_st;

struct sockaddr_in accept_sockaddr; //定义accept IP地址结构

socklen_t addrlen = sizeof(accept_sockaddr);

memset(&accept_sockaddr, 0, addrlen);

accept_st = accept(listen_st, (struct sockaddr*) &accept_sockaddr,&addrlen);

//accept 会阻塞直到客户端连接连过来 服务端这个socket只负责listen 是不是有客服端连接过来了

//是通过accept返回socket通信的

if (accept_st == -1)

{

printf("accept error:%s \n", strerror(errno));

return ERRORCODE;

}

printf("accpet ip:%s \n", inet_ntoa(accept_sockaddr.sin_addr));

return accept_st;

}

int run_server(int port)

{

int listen_st = create_listen(port); //创建监听socket

pthread_t send_thrd, recv_thrd;

struct pthread_socket ps;

int accept_st;

if (listen_st == -1)

{

return ERRORCODE;

}

printf("server start \n");

while (1)

{

accept_st = accept_socket(listen_st); //获取连接的的socket

if (accept_st == -1)

{

return ERRORCODE;

}

if (count_connect >= MAXCONN)

{

printf("connect have already be full! \n");

close(accept_st);

continue;

}

pthread_mutex_lock(&mutex);

count_connect++;

pthread_mutex_unlock(&mutex);

if (pthread_create(&send_thrd, NULL, thread_send, &accept_st) != 0) //创建发送信息线程

{

printf("create thread error:%s \n", strerror(errno));

break;

}

pthread_detach(send_thrd); //设置线程可分离性,这样的话主线程就不用join

ps.socket_d = accept_st;

ps.thrd = send_thrd;

if (pthread_create(&recv_thrd, NULL, thread_recv, &ps) != 0)//创建接收信息线程

{

printf("create thread error:%s \n", strerror(errno));

break;

}

pthread_detach(recv_thrd); //设置线程为可分离,这样的话,就不用pthread_join

}

close(accept_st);

close(listen_st);

return 0;

}

//server main

int main(int argc, char *argv[])

{

if (argc < 2)

{

printf("Usage:port,example:8080 \n");

return -1;

}

int port = atoi(argv[1]);

if (port == 0)

{

printf("port error! \n");

}

else

{

run_server(port);

}

return 0;

}

 

客户端:

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define BUFFSIZE 1024

#define ERRORCODE -1

static void *thread_send(void *arg)

{

char buf[BUFFSIZE];

int sd = *(int *) arg;

while (1)

{

memset(buf, 0, sizeof(buf));

read(STDIN_FILENO, buf, sizeof(buf));

if (send(sd, buf, strlen(buf), 0) == -1)

{

printf("send error:%s \n", strerror(errno));

break;

}

}

return NULL;

}

static void *thread_recv(void *arg)

{

char buf[BUFFSIZE];

int sd = *(int *) arg;

while (1)

{

memset(buf, 0, sizeof(buf));

int rv = recv(sd, buf, sizeof(buf), 0);

if (rv <= 0)

{

if(rv == 0) //server socket关闭情况

{

printf("server have already full !\n");

exit(0);//退出整个客服端

}

printf("recv error:%s \n", strerror(errno));

break;

}

printf("%s", buf);//输出接收到的内容

}

return NULL;

}

int run_client(char *ip_str, int port)

{

int client_sd;

int con_rv;

pthread_t thrd1, thrd2;

struct sockaddr_in client_sockaddr; //定义IP地址结构

client_sd = socket(AF_INET, SOCK_STREAM, 0);

if (client_sd == -1)

{

printf("socket create error:%s \n", strerror(errno));

return ERRORCODE;

}

memset(&client_sockaddr, 0, sizeof(client_sockaddr));

client_sockaddr.sin_port = htons(port); //指定一个端口号并将hosts字节型传化成Inet型字节型(大端或或者小端问题)

client_sockaddr.sin_family = AF_INET; //设置结构类型为TCP/IP

client_sockaddr.sin_addr.s_addr = inet_addr(ip_str);//将字符串的ip地址转换成int型,客服端要连接的ip地址

con_rv = connect(client_sd, (struct sockaddr*) &client_sockaddr,

sizeof(client_sockaddr));

//调用connect连接到指定的ip地址和端口号,建立连接后通过socket描述符通信

if (con_rv == -1)

{

printf("connect error:%s \n", strerror(errno));

return ERRORCODE;

}

if (pthread_create(&thrd1, NULL, thread_send, &client_sd) != 0)

{

printf("thread error:%s \n", strerror(errno));

return ERRORCODE;

}

if (pthread_create(&thrd2, NULL, thread_recv, &client_sd) != 0)

{

printf("thread error:%s \n", strerror(errno));

return ERRORCODE;

}

pthread_join(thrd2, NULL);// 等待线程退出

pthread_join(thrd1, NULL);

close(client_sd);

return 0;

}

int main(int argc, char *argv[])

{

if (argc < 3)

{

printf("Usage:ip port,example:127.0.0.1 8080 \n");

return ERRORCODE;

}

int port = atoi(argv[2]);

char *ip_str = argv[1];

run_client(ip_str,port);

return 0;

}

 g++ -pthread socket.c -o socketTest 

转自:https://blog.csdn.net/cike44/article/details/52756900/

字节流套接口(如tcp套接口)上的read和write函数所表现的行为不同于通常的文件IO。字节流套接口上的读或写输入或输出的字节数可能比要求的数量少,但这不是错误状况,原因是内核中套接口的缓冲区可能已达到了极限。此时所需的是调用者再次调用read或write函数,以输入或输出剩余的字节。 

可以使用readn函数来实现循环读取以解决这个问题:

ssize_t /* Read "n" bytes from a descriptor. */

readn(int fd, void *vptr, size_t n)

{

size_t nleft;

ssize_t nread;

char *ptr;

ptr = vptr;

nleft = n;

while (nleft > 0) {

if ( (nread = read(fd, ptr, nleft)) < 0) {

if (errno == EINTR)

nread = 0; /* and call read() again */

else

return(-1);

} else if (nread == 0)

break; /* EOF */

nleft -= nread;

ptr += nread;

}

return(n - nleft); /* return >= 0 */

}

socket编程中recv()和read()的使用与区别_HW_Coder0501的博客-CSDN博客_recv

Windows下C语言的Socket编程例子

2017-12-21 13:32:23

TCP服务端通信的常规步骤:

使用 socket() 创建 TCP 套接字(socket)将创建的套接字绑定到一个本地地址和端口上(Bind)将套接字设为监听模式,准备接收客户端请求(listen)等待客户请求到来: 当请求到来后,接受连接请求,返回一个对应于此次连接的新的套接字(accept)用 accept 返回的套接字和客户端进行通信(使用 write() / send() 或 send() / recv() )返回,等待另一个客户请求关闭套接字

TCP客户端通信的常规步骤:

创建套接字(socket)使用 connect() 建立到达服务器的连接(connect)客户端进行通信(使用 write() / send() 或 send() / recv() )使用 close() 关闭客户连接

一。  TCP

server端:

 C++ Code 

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 #include "stdafx.h" #include  #include  #pragma comment(lib,"ws2_32.lib") int main(int argc, char* argv[]) {     //初始化WSA     WORD sockVersion = MAKEWORD(2,2);     WSADATA wsaData;     if(WSAStartup(sockVersion, &wsaData)!=0)     {         return 0;     }     //创建套接字     SOCKET slisten = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);     if(slisten == INVALID_SOCKET)     {         printf("socket error !");         return 0;     }     //绑定IP和端口     sockaddr_in sin;     sin.sin_family = AF_INET;     sin.sin_port = htons(8888);     sin.sin_addr.S_un.S_addr = INADDR_ANY;      if(bind(slisten, (LPSOCKADDR)&sin, sizeof(sin)) == SOCKET_ERROR)     {         printf("bind error !");     }     //开始监听     if(listen(slisten, 5) == SOCKET_ERROR)     {         printf("listen error !");         return 0;     }     //循环接收数据     SOCKET sClient;     sockaddr_in remoteAddr;     int nAddrlen = sizeof(remoteAddr);     char revData[255];      while (true)     {         printf("等待连接...\n");         sClient = accept(slisten, (SOCKADDR *)&remoteAddr, &nAddrlen);         if(sClient == INVALID_SOCKET)         {             printf("accept error !");             continue;         }         printf("接受到一个连接:%s \r\n", inet_ntoa(remoteAddr.sin_addr));                  //接收数据         int ret = recv(sClient, revData, 255, 0);                 if(ret > 0)         {             revData[ret] = 0x00;             printf(revData);         }         //发送数据         char * sendData = "你好,TCP客户端!\n";         send(sClient, sendData, strlen(sendData), 0);         closesocket(sClient);     }          closesocket(slisten);     WSACleanup();     return 0; }

client端:

 C++ Code 

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 #include #include #include #include #pragma  comment(lib,"ws2_32.lib") int main(int argc, char *argv[]) {     WORD sockVersion = MAKEWORD(2, 2);     WSADATA data;     if(WSAStartup(sockVersion, &data) != 0)     {         return 0;     }     SOCKET sclient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);     if(sclient == INVALID_SOCKET)     {         printf("invalid socket !");         return 0;     }     sockaddr_in serAddr;     serAddr.sin_family = AF_INET;     serAddr.sin_port = htons(8888);     serAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");     if (connect(sclient, (sockaddr *)&serAddr, sizeof(serAddr)) == SOCKET_ERROR)     {         printf("connect error !");         closesocket(sclient);         return 0;     }     char *sendData = "你好,TCP服务端,我是客户端!\n";     send(sclient, sendData, strlen(sendData), 0);     char recData[255];     int ret = recv(sclient, recData, 255, 0);     if(ret > 0)     {         recData[ret] = 0x00;         printf(recData);     }     closesocket(sclient);     WSACleanup();     return 0; }

二.UDP

SERVER 端

 C++ Code 

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 #include "stdafx.h" #include  #include  #pragma comment(lib, "ws2_32.lib")  int main(int argc, char* argv[]) {     WSADATA wsaData;     WORD sockVersion = MAKEWORD(2,2);     if(WSAStartup(sockVersion, &wsaData) != 0)     {         return 0;     }     SOCKET serSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);      if(serSocket == INVALID_SOCKET)     {         printf("socket error !");         return 0;     }     sockaddr_in serAddr;     serAddr.sin_family = AF_INET;     serAddr.sin_port = htons(8888);     serAddr.sin_addr.S_un.S_addr = INADDR_ANY;     if(bind(serSocket, (sockaddr *)&serAddr, sizeof(serAddr)) == SOCKET_ERROR)     {         printf("bind error !");         closesocket(serSocket);         return 0;     }          sockaddr_in remoteAddr;     int nAddrLen = sizeof(remoteAddr);      while (true)     {         char recvData[255];           int ret = recvfrom(serSocket, recvData, 255, 0, (sockaddr *)&remoteAddr, &nAddrLen);         if (ret > 0)         {             recvData[ret] = 0x00;             printf("接受到一个连接:%s \r\n", inet_ntoa(remoteAddr.sin_addr));             printf(recvData);                     }         char * sendData = "一个来自服务端的UDP数据包\n";         sendto(serSocket, sendData, strlen(sendData), 0, (sockaddr *)&remoteAddr, nAddrLen);         }     closesocket(serSocket);      WSACleanup();     return 0; }

 C++ Code 

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 #include "stdafx.h" #include  #include  #pragma comment(lib, "ws2_32.lib")  int main(int argc, char* argv[]) {     WORD socketVersion = MAKEWORD(2,2);     WSADATA wsaData;      if(WSAStartup(socketVersion, &wsaData) != 0)     {         return 0;     }     SOCKET sclient = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);          sockaddr_in sin;     sin.sin_family = AF_INET;     sin.sin_port = htons(8888);     sin.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");     int len = sizeof(sin);          char * sendData = "来自客户端的数据包.\n";     sendto(sclient, sendData, strlen(sendData), 0, (sockaddr *)&sin, len);     char recvData[255];          int ret = recvfrom(sclient, recvData, 255, 0, (sockaddr *)&sin, &len);     if(ret > 0)     {         recvData[ret] = 0x00;         printf(recvData);     }     closesocket(sclient);     WSACleanup();     return 0; }

本文来至:http://blog.csdn.net/ssun125/article/details/8525823

Socket send函数和recv函数详解

2018-01-23 02:03:23

1.send 函数

int send( SOCKET s, const char FAR *buf, int len, int flags );  

    不论是客户还是服务器应用程序都用send函数来向TCP连接的另一端发送数据。客户程序一般用send函数向服务器发送请求,而服务器则通常用send函数来向客户程序发送应答。

    该函数的第一个参数指定发送端套接字描述符;

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

    第三个参数指明实际要发送的数据的字节数;

    第四个参数一般置0。 

    这里只描述同步Socket的send函数的执行流程。当调用该函数时,

   (1)send先比较待发送数据的长度len和套接字s的发送缓冲的长度, 如果len大于s的发送缓冲区的长度,该函数返回SOCKET_ERROR;

   (2)如果len小于或者等于s的发送缓冲区的长度,那么send先检查协议是否正在发送s的发送缓冲中的数据,如果是就等待协议把数据发送完,如果协议还没有开始发送s的发送缓冲中的数据或者s的发送缓冲中没有数据,那么send就比较s的发送缓冲区的剩余空间和len

   (3)如果len大于剩余空间大小,send就一直等待协议把s的发送缓冲中的数据发送完

   (4)如果len小于剩余 空间大小,send就仅仅把buf中的数据copy到剩余空间里(注意并不是send把s的发送缓冲中的数据传到连接的另一端的,而是协议传的,send仅仅是把buf中的数据copy到s的发送缓冲区的剩余空间里)。

   如果send函数copy数据成功,就返回实际copy的字节数,如果send在copy数据时出现错误,那么send就返回SOCKET_ERROR;如果send在等待协议传送数据时网络断开的话,那么send函数也返回SOCKET_ERROR。

   要注意send函数把buf中的数据成功copy到s的发送缓冲的剩余空间里后它就返回了,但是此时这些数据并不一定马上被传到连接的另一端。如果协议在后续的传送过程中出现网络错误的话,那么下一个Socket函数就会返回SOCKET_ERROR。(每一个除send外的Socket函数在执 行的最开始总要先等待套接字的发送缓冲中的数据被协议传送完毕才能继续,如果在等待时出现网络错误,那么该Socket函数就返回 SOCKET_ERROR)

注意:在Unix系统下,如果send在等待协议传送数据时网络断开的话,调用send的进程会接收到一个SIGPIPE信号,进程对该信号的默认处理是进程终止。

通过测试发现,异步socket的send函数在网络刚刚断开时还能发送返回相应的字节数,同时使用select检测也是可写的,但是过几秒钟之后,再send就会出错了,返回-1。select也不能检测出可写了。

 

2. recv函数

int recv( SOCKET s, char FAR *buf, int len, int flags);   

    不论是客户还是服务器应用程序都用recv函数从TCP连接的另一端接收数据。该函数的第一个参数指定接收端套接字描述符;

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

    第三个参数指明buf的长度;

    第四个参数一般置0。

    这里只描述同步Socket的recv函数的执行流程。当应用程序调用recv函数时,

    (1)recv先等待s的发送缓冲中的数据被协议传送完毕,如果协议在传送s的发送缓冲中的数据时出现网络错误,那么recv函数返回SOCKET_ERROR,

    (2)如果s的发送缓冲中没有数据或者数据被协议成功发送完毕后,recv先检查套接字s的接收缓冲区,如果s接收缓冲区中没有数据或者协议正在接收数据,那么recv就一直等待,直到协议把数据接收完毕。当协议把数据接收完毕,recv函数就把s的接收缓冲中的数据copy到buf中(注意协议接收到的数据可能大于buf的长度,所以 在这种情况下要调用几次recv函数才能把s的接收缓冲中的数据copy完。recv函数仅仅是copy数据,真正的接收数据是协议来完成的),

    recv函数返回其实际copy的字节数。如果recv在copy时出错,那么它返回SOCKET_ERROR;如果recv函数在等待协议接收数据时网络中断了,那么它返回0。

注意:在Unix系统下,如果recv函数在等待协议接收数据时网络断开了,那么调用recv的进程会接收到一个SIGPIPE信号,进程对该信号的默认处理是进程终止。

【Socket】有很多BUG,测试人员要注意。

最近使用Scoket来测试链路和数据传输,发现Scoket有很多的bug,第一:十六进制发送的时候,数据中间的空格和你再输入框内的数据间加了空格然后再删掉,然后把数据发送出去,接收到的数据长度和数据竟然前后不一样。

第二、Scoket接收数据16进制显示总是在前面或者后面加一些额外的东西,比如在前面加0A(回车符?)时有时无。

编程知识

网络字节序与主机字节序

主机字节序就是我们平常说的大端和小端模式:不同的CPU有不同的字节序类型,这些字节序是指整数在内存中保存的顺序,这个叫做主机序。引用标准的Big-Endian和Little-Endian的定义如下:

  a) Little-Endian就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。

  b) Big-Endian就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。

网络字节序:4个字节的32 bit值以下面的次序传输:首先是0~7bit,其次8~15bit,然后16~23bit,最后是24~31bit。这种传输次序称作大端字节序。由于TCP/IP首部中所有的二进制整数在网络中传输时都要求以这种次序,因此它又称作网络字节序。字节序,顾名思义字节的顺序,就是大于一个字节类型的数据在内存中的存放顺序,一个字节的数据没有顺序的问题了。

所以:在将一个地址绑定到socket的时候,请先将主机字节序转换成为网络字节序,而不要假定主机字节序跟网络字节序一样使用的是Big-Endian。由于这个问题曾引发过血案!公司项目代码中由于存在这个问题,导致了很多莫名其妙的问题,所以请谨记对主机字节序不要做任何假定,务必将其转化为网络字节序再赋给socket。

4、socket中TCP的三次握手建立连接详解

我们知道tcp建立连接要进行“三次握手”,即交换三个分组。大致流程如下:

客户端向服务器发送一个SYN J服务器向客户端响应一个SYN K,并对SYN J进行确认ACK J+1客户端再想服务器发一个确认ACK K+1

只有就完了三次握手,但是这个三次握手发生在socket的那几个函数中呢?请看下图:

​编辑

图1、socket中发送的TCP三次握手

从图中可以看出,当客户端调用connect时,触发了连接请求,向服务器发送了SYN J包,这时connect进入阻塞状态;服务器监听到连接请求,即收到SYN J包,调用accept函数接收请求向客户端发送SYN K ,ACK J+1,这时accept进入阻塞状态;客户端收到服务器的SYN K ,ACK J+1之后,这时connect返回,并对SYN K进行确认;服务器收到ACK K+1时,accept返回,至此三次握手完毕,连接建立。

总结:客户端的connect在三次握手的第二个次返回,而服务器端的accept在三次握手的第三次返回。

5、socket中TCP的四次握手释放连接详解

上面介绍了socket中TCP的三次握手建立过程,及其涉及的socket函数。现在我们介绍socket中的四次握手释放连接的过程,请看下图:

​编辑

图2、socket中发送的TCP四次握手

图示过程如下:

某个应用进程首先调用close主动关闭连接,这时TCP发送一个FIN M; 另一端接收到FIN M之后,执行被动关闭,对这个FIN进行确认。它的接收也作为文件结束符传递给应用进程,因为FIN的接收意味着应用进程在相应的连接上再也接收不到额外数据; 一段时间之后,接收到文件结束符的应用进程调用close关闭它的socket。这导致它的TCP也发送一个FIN N; 接收到这个FIN的源发送端TCP对它进行确认。

这样每个方向上都有一个FIN和ACK。

 Socket在Linux中的表示

带有ID的文件

0:标准输入文件,对应键盘1:标准输出文件,对应显示器

一个文件描述符只是一个和打开的文件相关联的整数,背后代表的意思可能如下:

普通文件FIFO管道终端键盘显示器一个网络连接

socket()的返回值就是文件描述符

read(): 读取远程计算机传来的数据write():向远程计算机写入数据

Socket套接字类型

流格式套接字(SOCK_STREAM)

特征

数据在传输的过程中不会消失(只要SOCK_STREAM不消失,数据就不会消失)数据按顺序传输数据的发送和接收不同步

流格式套接字内部有一个缓冲区,通过socket传输的数据将保存在这个缓冲区中。接收端手法哦数据后并不是立即读取,只要数据不超过缓冲区容量,接收端可以在缓冲区被填满之后一次性读取,也可以分多次读取。(接收端可以控制数据的读取)

数据报套接字(SOCK_DGRAM)

无连接的套接字,用SOCK_DGRAM表示

只管传输数据,不做数据校验。

优缺点:传输效率快但是不能保证数据的有效性(数据会丢失)

特点:

强调快速传输而非传输顺序传输的数据可能丢失也可能损毁限制每次传输的数据大小数据的发送和接收是同步的(也叫:存在数据边界)

QQ视频聊天和语音聊天则使用SOCK_DRRAM来传输数据,首先先保证通信效率,降低延迟,视频和音频即使丢失一小部分数据,也不会对最终数据在终端的显示造成什么大的影响。

计算机网络相关知识点

IP地址MAC地址端口号:一台计算机可以同时提供多种网络服务(Web服务,FTP服务,SMTP服务),为区分不同的网络程序,计算机会为每个网络程序分配一个独一无二的端口号,不同计算机上的使用同一个端口通信的计算机可以通过这个端口号进行数据通信

Socket缓冲区

输入缓冲区输出缓冲区

write()/send()先将数据写入到缓冲区内部,再根据TCP协议将缓冲区中的数据发送到目标机器,一旦将数据写入缓冲区,函数就返回,不管后面的机器发送数据的过程。

read()/recv()函数从缓冲区读取数据,而不是从网络中读取数据。

缓冲区特性:

I/O缓冲区再每个套接字中单独存在I/O缓冲区在创建套接字时自动生成即使关闭套接字也会继续传送输出缓冲区中遗留的数据关闭套接字将丢失输入缓冲区中的数据

获取输入输出黄忠的大小:getsockopt()

unsigned optVal;

int optLen = sizeof(int);

getsockopt(servSock, SOL_SOCKET, SO_SNDBUF, (char*)&optVal, &optLen);

printf("Buffer length: %d\n", optVal);

阻塞IO

使用write()/send()发送数据时

先检查缓冲区,如果缓冲区的可用空间长度小于要发送的数据,则write()/send()会被阻塞,直到缓冲区中的数据被成功发送,缓冲区为空,才唤醒write()/send()继续写入数据如果程序在TCP协议下正在向网络发送数据,那么输出缓冲区会被锁定,不允许写入,write()/send()函数会被阻塞,直到数据发送完毕,才对缓冲区解锁,才将write()/send()唤醒如果要写入的数据大于缓冲区的最大长度,则将分批写入直到所有的数据被写入缓冲区write()/send()才能返回

当使用read()/recv()读取数据时:

先检查缓冲区,如果缓冲区中有数据,则读取;否则函数被阻塞,直到网络上有数据来如果要读取的数据长度小于缓冲区中的数据长度,则不能一次性将缓冲区中的所有数据读出,剩余数据将不断积压,直到有 read()/recv()函数再次读取。直到读取到数据后,read()/recv()函数才会返回,否则一直被阻塞

什么是TCP的粘包问题

对于Socket方式的数据发送和接收方式而言,数据的接收和数据发送是无关的,不管数据通过write()/send()发送了多少次,都会尽可能多的发送数据,根据上面的Socket中的内容可以看出,在服务端,只要你缓冲区为空,我就唤醒write()/send()进行数据的发送;而在服务端我则是等待read()/recv()可用的情况才对缓冲区中的数据进行读取,如此便会出现服务端和客户端数据发送/接收数据速率不同步的问题。因此可能会出现数据的**粘包问题。**举例如下:例如客户端向服务器第一次发送 1,第二次发送 3,服务器可能当成 13 来处理。

可以在上面的章节"Windows系统Socket通信程序Demo"让服务器线程在接收客户端数据前等待足够长的一段时间,比如:Sleep(10000);。可以很容易观测到客户端程序多次发送的数据在服务器端形成了"粘包问题"。

摘自:你不懂TCP/IP编程,面试官连面试你的机会都不给你! - 知乎

6、一个例子(实践一下)

说了这么多了,动手实践一下。下面编写一个简单的服务器、客户端(使用TCP)——服务器端一直监听本机的6666号端口,如果收到连接请求,将接收请求并接收客户端发来的消息;客户端与服务器端建立连接并发送一条消息。

服务器端代码:

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#define MAXLINE 4096 

int main(int argc, char** argv)

int listenfd, connfd; 

struct sockaddr_in servaddr; 

char buff[4096]; int n; 

if( (listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1 )

{

printf("create socket error: %s(errno: %d)\n",strerror(errno),errno);

exit(0);

}

memset(&servaddr, 0, sizeof(servaddr));

servaddr.sin_family = AF_INET;

servaddr.sin_addr.s_addr = htonl(INADDR_ANY);

servaddr.sin_port = htons(6666); 

if( bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) == -1)

{

printf("bind socket error: %s(errno: %d)\n",strerror(errno),errno);

exit(0);

if( listen(listenfd, 10) == -1)

{

printf("listen socket error: %s(errno: %d)\n",strerror(errno),errno);

exit(0);

}

printf("======waiting for client's request======\n"); 

while(1)

if( (connfd = accept(listenfd, (struct sockaddr*)NULL, NULL)) == -1)

{

printf("accept socket error: %s(errno: %d)",strerror(errno),errno); 

continue;

}

n= recv(connfd, buff, MAXLINE, 0);

buff[n] = '\0';

printf("recv msg from client: %s\n", buff);

close(connfd);

}

close(listenfd);

}

客户端代码:

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#define MAXLINE 4096 

int main(int argc, char** argv)

int sockfd, n; 

char recvline[4096], sendline[4096]; 

struct sockaddr_in servaddr; 

if( argc != 2)

{

printf("usage: ./client \n");

exit(0);

if( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)

{

printf("create socket error: %s(errno: %d)\n", strerror(errno),errno);

exit(0);

}

memset(&servaddr, 0, sizeof(servaddr));

servaddr.sin_family = AF_INET;

servaddr.sin_port =htons(6666); 

if( inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0)

{

printf("inet_pton error for %s\n",argv[1]);

exit(0);

if( connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0)

{

printf("connect error: %s(errno: %d)\n",strerror(errno),errno);

exit(0);

}

printf("send msg to server: \n"); fgets(sendline, 4096, stdin); 

if( send(sockfd, sendline, strlen(sendline), 0) < 0)

{

printf("send msg error: %s(errno: %d)\n", strerror(errno), errno);

exit(0);

}

close(sockfd);

exit(0);

}

当然上面的代码很简单,也有很多缺点,这就只是简单的演示socket的基本函数使用。其实不管有多复杂的网络程序,都使用的这些基本函数。上面的服务器使用的是迭代模式的,即只有处理完一个客户端请求才会去处理下一个客户端的请求,这样的服务器处理能力是很弱的,现实中的服务器都需要有并发处理能力!为了需要并发处理,服务器需要fork()一个新的进程或者线程去处理请求等。

7、动动手

留下一个问题,欢迎大家回帖回答!!!是否熟悉Linux下网络编程?如熟悉,编写如下程序完成如下功能:

服务器端:

接收地址192.168.100.2的客户端信息,如信息为“Client Query”,则打印“Receive Query”

客户端:

向地址192.168.100.168的服务器端顺序发送信息“Client Query test”,“Cleint Query”,“Client Query Quit”,然后退出。

题目中出现的ip地址可以根据实际情况定。

1、运行SQLPLUS工具

  C:\Users\wd-pc>sqlplus

2、直接进入SQLPLUS命令提示符

  C:\Users\wd-pc>sqlplus /nolog

3、以OS身份连接 

  C:\Users\wd-pc>sqlplus / as sysdba   或

  SQL>connect / as sysdba

4、普通用户登录

  C:\Users\wd-pc>sqlplus scott/123456  或

  SQL>connect scott/123456  或

  SQL>connect scott/123456@servername

5、以管理员登录

  C:\Users\wd-pc>sqlplus sys/123456 as sysdba 或

  SQL>connect sys/123456 as sysdba

6、切换用户

  SQL>conn hr/123456 

  注:conn同connect

 7、退出

  exit

原文;socket编程——一个简单的例子_find12的博客-CSDN博客_socket编程

接口函数(API)

3.1、socket()函数

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

socket函数对应于普通文件的打开操作。普通文件的打开操作返回一个文件描述字,而socket()用于创建一个socket描述符(socket descriptor),它唯一标识一个socket。这个socket描述字跟文件描述字一样,后续的操作都有用到它,把它作为参数,通过它来进行一些读写操作。

正如可以给fopen的传入不同参数值,以打开不同的文件。创建socket的时候,也可以指定不同的参数创建不同的socket描述符,socket函数的三个参数分别为:

domain:即协议域,又称为协议族(family)。常用的协议族有,AF_INET、AF_INET6、AF_LOCAL(或称AF_UNIX,Unix域socket)、AF_ROUTE等等。协议族决定了socket的地址类型,在通信中必须采用对应的地址,如AF_INET决定了要用ipv4地址(32位的)与端口号(16位的)的组合、AF_UNIX决定了要用一个绝对路径名作为地址。type:指定socket类型。常用的socket类型有,SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、SOCK_PACKET、SOCK_SEQPACKET等等(socket的类型有哪些?)。protocol:故名思意,就是指定协议。常用的协议有,IPPROTO_TCP、IPPTOTO_UDP、IPPROTO_SCTP、IPPROTO_TIPC等,它们分别对应TCP传输协议、UDP传输协议、STCP传输协议、TIPC传输协议(这个协议我将会单独开篇讨论!)。

注意:并不是上面的type和protocol可以随意组合的,如SOCK_STREAM不可以跟IPPROTO_UDP组合。当protocol为0时,会自动选择type类型对应的默认协议。

当我们调用socket创建一个socket时,返回的socket描述字它存在于协议族(address family,AF_XXX)空间中,但没有一个具体的地址。如果想要给它赋值一个地址,就必须调用bind()函数,否则就当调用connect()、listen()时系统会自动随机分配一个端口。

3.2、bind()函数

正如上面所说bind()函数把一个地址族中的特定地址赋给socket。例如对应AF_INET、AF_INET6就是把一个ipv4或ipv6地址和端口号组合赋给socket。

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

函数的三个参数分别为:

sockfd:即socket描述字,它是通过socket()函数创建了,唯一标识一个socket。bind()函数就是将给这个描述字绑定一个名字。addr:一个const struct sockaddr *指针,指向要绑定给sockfd的协议地址。这个地址结构根据地址创建socket时的地址协议族的不同而不同,如ipv4对应的是:  struct sockaddr_in {

sa_family_t sin_family; /* address family: AF_INET */

in_port_t sin_port; /* port in network byte order */

struct in_addr sin_addr; /* internet address */

};

/* Internet address. */

struct in_addr {

uint32_t s_addr; /* address in network byte order */

}; ipv6对应的是:  struct sockaddr_in6 {

sa_family_t sin6_family; /* AF_INET6 */

in_port_t sin6_port; /* port number */

uint32_t sin6_flowinfo; /* IPv6 flow information */

struct in6_addr sin6_addr; /* IPv6 address */

uint32_t sin6_scope_id; /* Scope ID (new in 2.4) */

};

struct in6_addr {

unsigned char s6_addr[16]; /* IPv6 address */

}; Unix域对应的是:  #define UNIX_PATH_MAX 108

struct sockaddr_un {

sa_family_t sun_family; /* AF_UNIX */

char sun_path[UNIX_PATH_MAX]; /* pathname */

};

addrlen:对应的是地址的长度。

通常服务器在启动的时候都会绑定一个众所周知的地址(如ip地址+端口号),用于提供服务,客户就可以通过它来接连服务器;而客户端就不用指定,有系统自动分配一个端口号和自身的ip地址组合。这就是为什么通常服务器端在listen之前会调用bind(),而客户端就不会调用,而是在connect()时由系统随机生成一个。

3.3、listen()、connect()函数

如果作为一个服务器,在调用socket()、bind()之后就会调用listen()来监听这个socket,如果客户端这时调用connect()发出连接请求,服务器端就会接收到这个请求。

int listen(int sockfd, int backlog);

int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

listen函数的第一个参数即为要监听的socket描述字,第二个参数为相应socket可以排队的最大连接个数。socket()函数创建的socket默认是一个主动类型的,listen函数将socket变为被动类型的,等待客户的连接请求。

connect函数的第一个参数即为客户端的socket描述字,第二参数为服务器的socket地址,第三个参数为socket地址的长度。客户端通过调用connect函数来建立与TCP服务器的连接。

3.4、accept()函数

TCP服务器端依次调用socket()、bind()、listen()之后,就会监听指定的socket地址了。TCP客户端依次调用socket()、connect()之后就想TCP服务器发送了一个连接请求。TCP服务器监听到这个请求之后,就会调用accept()函数取接收请求,这样连接就建立好了。之后就可以开始网络I/O操作了,即类同于普通文件的读写I/O操作。

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

accept函数的第一个参数为服务器的socket描述字,第二个参数为指向struct sockaddr *的指针,用于返回客户端的协议地址,第三个参数为协议地址的长度。如果accpet成功,那么其返回值是由内核自动生成的一个全新的描述字,代表与返回客户的TCP连接。

注意:accept的第一个参数为服务器的socket描述字,是服务器开始调用socket()函数生成的,称为监听socket描述字;而accept函数返回的是已连接的socket描述字。一个服务器通常通常仅仅只创建一个监听socket描述字,它在该服务器的生命周期内一直存在。内核为每个由服务器进程接受的客户连接创建了一个已连接socket描述字,当服务器完成了对某个客户的服务,相应的已连接socket描述字就被关闭。

3.5、read()、write()等函数

万事具备只欠东风,至此服务器与客户已经建立好连接了。可以调用网络I/O进行读写操作了,即实现了网咯中不同进程之间的通信!网络I/O操作有下面几组:

read()/write()recv()/send()readv()/writev()recvmsg()/sendmsg()recvfrom()/sendto()

我推荐使用recvmsg()/sendmsg()函数,这两个函数是最通用的I/O函数,实际上可以把上面的其它函数都替换成这两个函数。它们的声明如下:

#include

ssize_t read(int fd, void *buf, size_t count);

ssize_t write(int fd, const void *buf, size_t count);

#include

#include

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

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

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

const struct sockaddr *dest_addr, socklen_t addrlen);

ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,

struct sockaddr *src_addr, socklen_t *addrlen);

ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);

ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);

read函数是负责从fd中读取内容.当读成功时,read返回实际所读的字节数,如果返回的值是0表示已经读到文件的结束了,小于0表示出现了错误。如果错误为EINTR说明读是由中断引起的,如果是ECONNREST表示网络连接出了问题。

write函数将buf中的nbytes字节内容写入文件描述符fd.成功时返回写的字节数。失败时返回-1,并设置errno变量。 在网络程序中,当我们向套接字文件描述符写时有俩种可能。1)write的返回值大于0,表示写了部分或者是全部的数据。2)返回的值小于0,此时出现了错误。我们要根据错误类型来处理。如果错误为EINTR表示在写的时候出现了中断错误。如果为EPIPE表示网络连接出现了问题(对方已经关闭了连接)。

其它的我就不一一介绍这几对I/O函数了,具体参见man文档或者baidu、Google,下面的例子中将使用到send/recv。

3.6、close()函数

在服务器与客户端建立连接之后,会进行一些读写操作,完成了读写操作就要关闭相应的socket描述字,好比操作完打开的文件要调用fclose关闭打开的文件。

#include

int close(int fd);

close一个TCP socket的缺省行为时把该socket标记为以关闭,然后立即返回到调用进程。该描述字不能再由调用进程使用,也就是说不能再作为read或write的第一个参数。

注意:close操作只是使相应socket描述字的引用计数-1,只有当引用计数为0的时候,才会触发TCP客户端向服务器发送终止连接请求。

posted on

2022-10-04 01:29 

bdy 

阅读(2524) 

评论(0) 

编辑 

收藏 

举报

会员力量,点亮园子希望

刷新页面返回顶部

导航

博客园

首页

新随笔

联系

订阅

管理

公告

Powered by:

博客园

Copyright © 2024 bdy

Powered by .NET 8.0 on Kubernetes

网络编程:程序员的基本功!教你如何自学C语言网络编程! - 知乎

网络编程:程序员的基本功!教你如何自学C语言网络编程! - 知乎首发于程序员相关文章切换模式写文章登录/注册网络编程:程序员的基本功!教你如何自学C语言网络编程!C语言入门教学悟空问答丨大学生编程指南网络编程在编程体系里面占据很大一部分,在离不开网络的时代,网络编程重要性越来越强,网络编程算是程序员要掌握的基本功了,很多人好奇的黑客,网络也是基本功。无论什么编程语言都需要支持网络编程,只不过在接口实现方式上,会根据自身编程语言的特性,对于socket进行封装。网络编程经典书籍:《协议:TCP/IP卷一》《UNIX网络编程》网络编程底层代码基本上C语言来实现的,建议在linux下用c语言,把底层原汁原味的linux socket编程走一遍,下图是一个socket原理图:socket常见接口现在无论java,python网络接口都接近上面的接口。如何学?1.先把网络编程的基本概念了解明白,知道大概协议,读懂网络传输的原理(把推荐的两本书)2.选择一门自己擅长的编程语言(C/C++),然后在上面练习网路编程(选择编程环境)3.亲自手动写一个网络编程实例,例如实现简单的局域网数据传输功能,模拟简单的qq聊天功能(功能实践)——————————————————————————————————————笔者是一个C/C++出身的程序员,自学C/C++编程有什么学习问题或者关于C/C++学习的路线的话可以看我个人介绍交流。 发布于 2019-08-16 15:15网络编程C / C++UNIX网络编程(书籍)​赞同 5​​添加评论​分享​喜欢​收藏​申请转载​文章被以下专栏收录程序员相关文章C/C++程序员资料分享Q群:951258

网络编程-【自己动手】用C语言写一个基于服务器和客户端(TCP)! - 知乎

网络编程-【自己动手】用C语言写一个基于服务器和客户端(TCP)! - 知乎首发于C/C++编程学习殿堂切换模式写文章登录/注册网络编程-【自己动手】用C语言写一个基于服务器和客户端(TCP)!C语言编程俱乐部如果你想学编程可以关注我的专栏,欢迎到访~如果想要自己写一个服务器和客户端,我们需要掌握一定的网络编程技术,个人认为,网络编程中最关键的就是这个东西——socket(套接字)。socket(套接字):简单来讲,socket就是用于描述IP地址和端口,是一个通信链的句柄,可以用来实现不同虚拟机或不同计算机之间的通信。✁ TCP 协议TCP 协议:是一种面向连接的、可靠的、基于字节流的传输层通信协议,由IETF的RFC 793定义。在简化的计算机网络OSI模型中,它完成第四层传输层所指定的功能。关键词:三次握手,可靠,基于字节流。可能有朋友会问,TCP就这么简单一句话吗?当然不是,TCP作为非常重要的传输协议,细节知识是很多的,细讲起来这一篇文章怕是不够。不过在本篇内容中,我们只需了解他的几个关键词特性,就能很好的理解下面的内容。✁ TCP服务器端和客户端的运行流程如图,这是一个完整的TCP服务器——客户端的运行流程图,其实我个人认为程序啊,不管哪个语言都是一样,核心就在于算法的设计和函数的调用。那么图中的函数都是什么意思呢?1.创建socketsocket是一个结构体,被创建在内核中sockfd=socket(AF_INET,SOCK_STREAM,0); //AF_INT:ipv4, SOCK_STREAM:tcp协议2.调用bind函数将socket和地址(包括ip、port)绑定。需要定义一个结构体地址,以便于将port的主机字节序转化成网络字节序struct socka ddr_inmyaddr; //地址结构体 bind函数bind(sockfd,(structsockaddr*)&myaddr,sizeof(serveraddr))3.listen监听,将接收到的客户端连接放入队列listen(sockfd,8) //第二个参数是队列长度 4.调用accept函数,从队列获取请求,返回socket描 述符如果无请求,将会阻塞,直到获得连接int fd=accept(sockfd,NULL,NULL); //这边采用默认参数

5.调用read/write进行双向通信6.关闭accept返回的socketclose(scokfd); 下面放出完整代码:如果你也想学编程,可以来我的C语言/C++编程学习基地【点击进入】!还有免费的(源码,零基础教程,项目实战教学视频)! 涉及:游戏开发、课程设计、常用软件开发、编程基础知识、黑客等等.../*服务器*/

#include

#include

#include

#include

#include

#include

#include

#include

int main()

{

int sockfd = socket(AF_INET, SOCK_STREAM, 0);//创建套接字

if (sockfd < 0)

{

perror("socket");

return -1;

} //创建失败的错误处理

printf("socket..............\n"); //成功则打印“socket。。。。”

struct sockaddr_in myaddr; //创建“我的地址”结构体

memset(&myaddr, 0, sizeof(myaddr)); //对内存清零(保险起见)

myaddr.sin_family = AF_INET; //选择IPV4地址类型

myaddr.sin_port = htons(8888); //选择端口号

myaddr.sin_addr.s_addr = inet_addr("192.168.3.169"); //选择IP地址

if (0 > bind(sockfd, (struct sockaddr*)&myaddr, sizeof(myaddr)))//绑定套接字

{

perror("bind");

return -1;

}

printf("bind..........\n");

if (0 > listen(sockfd, 8))//调用listen对指定端口进行监听

{

perror("listen");

return -1;

}

printf("listen............\n");

int connfd = accept(sockfd, NULL, NULL);//使用accept从消息队列中获取请求

if (connfd < 0)

{

perror("accept");

return -1;

}

printf("accept..............\n");

char buf[100];//定义一个数组用来存储接收到的数据

int ret;

while (1)

{

memset(buf, 0, sizeof(buf));

ret = read(connfd, buf, sizeof(buf));

if (0 > ret)

{

perror("read");

break;

}//执行while循环读取数据,当

else if (0 == ret)

{

printf("write close!\n");

break;

}

printf("recv: ");

fputs(buf, stdout);//打印接收到的数据

}

close(sockfd);//关闭套接字

close(connfd);//断开连接

return 0;

}

/*客户端*/(具体功能和服务器一样,所以不再加注释)

#include

#include

#include

#include

#include

#include

#include

#include

int main()

{

int sockfd;

if (0 > (sockfd = socket(AF_INET, SOCK_STREAM, 0)))

{

perror("socket");

return -1;

}

printf("socket...........\n");

struct sockaddr_in srv_addr;

memset(&srv_addr, 0, sizeof(srv_addr));

srv_addr.sin_family = AF_INET;

srv_addr.sin_port = htons(8888);

srv_addr.sin_addr.s_addr = inet_addr("192.168.3.169");

if (0 > connect(sockfd, (struct sockaddr*)&srv_addr, sizeof(srv_addr)))

{

perror("connect");

return -1; //exit //pthread_exit

}

printf("connect..............\n");

char buf[100];

int ret;

while (1)

{

printf("send: ");

fgets(buf, sizeof(buf), stdin);

ret = write(sockfd, buf, sizeof(buf));

if (ret < 0)

{

perror("write");

break;

}

if (strncmp(buf, "quit", 4) == 0)

break;

}

close(sockfd);

return 0;

} 发布于 2020-08-10 14:14网络编程SocketC(编程语言)​赞同 13​​1 条评论​分享​喜欢​收藏​申请转载​文章被以下专栏收录C/C++编程学习殿堂编程技术学习交流Q群:759452

网络编程 - 廖雪峰的官方网站

网络编程 - 廖雪峰的官方网站

Index

廖雪峰的官方网站

Blog

Java教程

手写Spring

手写Tomcat

Makefile教程

Python教程

JavaScript教程

区块链教程

SQL教程

Git教程

文章

问答

More

Java教程

手写Spring

手写Tomcat

Makefile教程

Python教程

JavaScript教程

区块链教程

SQL教程

Git教程

文章

问答

Java教程

手写Spring

手写Tomcat

Makefile教程

Python教程

JavaScript教程

区块链教程

SQL教程

Git教程

文章

问答

 

Profile

Passkey

Sign Out

Sign In

English

简体中文

Index

Python教程

Python简介

安装Python

Python解释器

第一个Python程序

使用文本编辑器

Python代码运行助手

输入和输出

Python基础

数据类型和变量

字符串和编码

使用list和tuple

条件判断

模式匹配

循环

使用dict和set

函数

调用函数

定义函数

函数的参数

递归函数

高级特性

切片

迭代

列表生成式

生成器

迭代器

函数式编程

高阶函数

map/reduce

filter

sorted

返回函数

匿名函数

装饰器

偏函数

模块

使用模块

安装第三方模块

面向对象编程

类和实例

访问限制

继承和多态

获取对象信息

实例属性和类属性

面向对象高级编程

使用__slots__

使用@property

多重继承

定制类

使用枚举类

使用元类

错误、调试和测试

错误处理

调试

单元测试

文档测试

IO编程

文件读写

StringIO和BytesIO

操作文件和目录

序列化

进程和线程

多进程

多线程

ThreadLocal

进程 vs. 线程

分布式进程

正则表达式

常用内建模块

datetime

collections

argparse

base64

struct

hashlib

hmac

itertools

contextlib

urllib

XML

HTMLParser

常用第三方模块

Pillow

requests

chardet

psutil

venv

图形界面

海龟绘图

网络编程

TCP/IP简介

TCP编程

UDP编程

电子邮件

SMTP发送邮件

POP3收取邮件

访问数据库

使用SQLite

使用MySQL

使用SQLAlchemy

Web开发

HTTP协议简介

HTML简介

WSGI接口

使用Web框架

使用模板

异步IO

协程

asyncio

async/await

aiohttp

使用MicroPython

搭建开发环境

控制小车

遥控小车

遥控转向

实战

Day 1 - 搭建开发环境

Day 2 - 编写Web App骨架

Day 3 - 编写ORM

Day 4 - 编写Model

Day 5 - 编写Web框架

Day 6 - 编写配置文件

Day 7 - 编写MVC

Day 8 - 构建前端

Day 9 - 编写API

Day 10 - 用户注册和登录

Day 11 - 编写日志创建页

Day 12 - 编写日志列表页

Day 13 - 提升开发效率

Day 14 - 完成Web App

Day 15 - 部署Web App

Day 16 - 编写移动App

FAQ

期末总结

关注公众号不定期领红包:

加入知识星球社群:

关注微博获取实时动态:

网络编程

Last updated: ...

/

Reads: 42034298

Edit

自从互联网诞生以来,现在基本上所有的程序都是网络程序,很少有单机版的程序了。

计算机网络就是把各个计算机连接到一起,让网络中的计算机可以互相通信。网络编程就是如何在程序中实现两台计算机的通信。

举个例子,当你使用浏览器访问新浪网时,你的计算机就和新浪的某台服务器通过互联网连接起来了,然后,新浪的服务器把网页内容作为数据通过互联网传输到你的电脑上。

由于你的电脑上可能不止浏览器,还有QQ、Skype、Dropbox、邮件客户端等,不同的程序连接的别的计算机也会不同,所以,更确切地说,网络通信是两台计算机上的两个进程之间的通信。比如,浏览器进程和新浪服务器上的某个Web服务进程在通信,而QQ进程是和腾讯的某个服务器上的某个进程在通信。

网络编程对所有开发语言都是一样的,Python也不例外。用Python进行网络编程,就是在Python程序本身这个进程内,连接别的服务器进程的通信端口进行通信。

本章我们将详细介绍Python网络编程的概念和最主要的两种网络类型的编程。

Comments

Make a comment

Sign in to

make a comment

Index

Python教程

Python简介

安装Python

Python解释器

第一个Python程序

使用文本编辑器

Python代码运行助手

输入和输出

Python基础

数据类型和变量

字符串和编码

使用list和tuple

条件判断

模式匹配

循环

使用dict和set

函数

调用函数

定义函数

函数的参数

递归函数

高级特性

切片

迭代

列表生成式

生成器

迭代器

函数式编程

高阶函数

map/reduce

filter

sorted

返回函数

匿名函数

装饰器

偏函数

模块

使用模块

安装第三方模块

面向对象编程

类和实例

访问限制

继承和多态

获取对象信息

实例属性和类属性

面向对象高级编程

使用__slots__

使用@property

多重继承

定制类

使用枚举类

使用元类

错误、调试和测试

错误处理

调试

单元测试

文档测试

IO编程

文件读写

StringIO和BytesIO

操作文件和目录

序列化

进程和线程

多进程

多线程

ThreadLocal

进程 vs. 线程

分布式进程

正则表达式

常用内建模块

datetime

collections

argparse

base64

struct

hashlib

hmac

itertools

contextlib

urllib

XML

HTMLParser

常用第三方模块

Pillow

requests

chardet

psutil

venv

图形界面

海龟绘图

网络编程

TCP/IP简介

TCP编程

UDP编程

电子邮件

SMTP发送邮件

POP3收取邮件

访问数据库

使用SQLite

使用MySQL

使用SQLAlchemy

Web开发

HTTP协议简介

HTML简介

WSGI接口

使用Web框架

使用模板

异步IO

协程

asyncio

async/await

aiohttp

使用MicroPython

搭建开发环境

控制小车

遥控小车

遥控转向

实战

Day 1 - 搭建开发环境

Day 2 - 编写Web App骨架

Day 3 - 编写ORM

Day 4 - 编写Model

Day 5 - 编写Web框架

Day 6 - 编写配置文件

Day 7 - 编写MVC

Day 8 - 构建前端

Day 9 - 编写API

Day 10 - 用户注册和登录

Day 11 - 编写日志创建页

Day 12 - 编写日志列表页

Day 13 - 提升开发效率

Day 14 - 完成Web App

Day 15 - 部署Web App

Day 16 - 编写移动App

FAQ

期末总结

廖雪峰的官方网站

©Copyright 2019-2021

Powered by iTranswarp

Feedback

License

C语言网络编程(1)— UDP通信(这篇写得很详细,也讲了怎么借助网络调试助手)_udp c语言代码-CSDN博客

>

C语言网络编程(1)— UDP通信(这篇写得很详细,也讲了怎么借助网络调试助手)_udp c语言代码-CSDN博客

C语言网络编程(1)— UDP通信(这篇写得很详细,也讲了怎么借助网络调试助手)

最新推荐文章于 2023-11-14 14:27:13 发布

诗筱涵

最新推荐文章于 2023-11-14 14:27:13 发布

阅读量1w

收藏

106

点赞数

21

分类专栏:

# 网络编程(Linux应用层编程)

无人机-a-个人笔记

原文链接:https://blog.csdn.net/qq_38113006/article/details/105531439

版权

无人机-a-个人笔记

同时被 2 个专栏收录

251 篇文章

62 订阅

订阅专栏

网络编程(Linux应用层编程)

91 篇文章

13 订阅

订阅专栏

这篇写得很详细,也讲了怎么借助网络调试助手,而且从这篇来看,写起来确实挺简单的。

转载自:https://blog.csdn.net/qq_38113006/article/details/105531439

C语言网络编程(1)— UDP通信

Willliam_william 2020-04-15 13:56:37 1465 收藏 22

分类专栏: C语言网络编程

版权

C语言网络编程(1)— UDP通信

一、socket

我们要进行网络通信,那么就要用到socket,socket即网络套接字,应用程序可以通过它发送或接收数据,可对其进行像对文件一样的打开、读写和关闭等操作。 在 C语言中,有支持socket 的库,使用库里的socket()函数 就可以创建一个socket对象,socket()函数原型是

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

其中domain参数是指协议域,又称为协议族(family),常用的协议族有,AF_INET、AF_INET6、…等等,AF_INET指ipv4,AF_INET6即为ipv6;然后是type,type指定socket类型,有SOCK_STREAM(流式套接字,主要用于 TCP 协议)和SOCK_DGRAM(数据报套接字,主要用于 UDP 协议)等等;protocol就是指定的协议,常用的协议有,IPPROTO_TCP、IPPTOTO_UDP、IPPROTO_SCTP、IPPROTO_TIPC等,它们分别对应TCP传输协议、UDP传输协议、STCP传输协议、TIPC传输协议,但是type和proto不可以随意组合,当protocol参数为0时,会自动选择type类型对应的默认协议。

二、UDP发送数据

首先我们添加要使用的头文件

#include

#include

#include

#include

#include

#include

创建一个udp套接字,ipv4协议,使用SOCK_DGRAM参数,protocol为0,就会默认自动选择udp协议;

// 1、使用socket()函数获取一个socket文件描述符

int sockfd = socket(AF_INET, SOCK_DGRAM, 0);

然后我们把要接收数据的那一端的ip地址和端口号放在一个结构体里准备好

// 2. 准备接收方的地址和端口,'192.168.0.107'表示目的ip地址,8080表示目的端口号

struct sockaddr_in sock_addr = {0};

sock_addr.sin_family = AF_INET; // 设置地址族为IPv4

sock_addr.sin_port = htons(8266); // 设置地址的端口号信息

sock_addr.sin_addr.s_addr = inet_addr("192.168.0.107"); // 设置IP地址

准备好后就可以使用sendto函数进行发送了,对于sendto()函数,成功则返回实际传送出去的字符数,失败返回-1,

// 3. 发送数据到指定的ip和端口

char sendbuf[]={"hello world."};

ret = sendto(sockfd, sendbuf, sizeof(sendbuf), 0, (struct sockaddr*)&sock_addr, sizeof(sock_addr));

发送完就可以关闭套接字了

// 4. 关闭套接字

close(sockfd);

打开网络调试助手,编译,运行程序,可以看到,数据发送成功,且网络调试助手已经接收到数据了,注意,如果不是在本机windows系统上运行python程序,在Ubuntu虚拟机或者其他局域网内的机器上运行,要把windows的防火墙关了,重要的事说三遍!!!注意,如果不是在本机windows系统上运行python程序,在Ubuntu虚拟机或者其他局域网内的机器上运行,要把windows的防火墙关了,重要的事说三遍!!!注意,如果不是在本机windows系统上运行python程序,在Ubuntu虚拟机或者其他局域网内的机器上运行,要把windows的防火墙关了,重要的事说三遍!!! 然后我们让其每隔一秒发送一次,发送10次,发送成功 贴上完整代码:

#include

#include

#include

#include

#include

#include

int main(void)

{

int ret = -1;

// 1、使用socket()函数获取一个socket文件描述符

int sockfd = socket(AF_INET, SOCK_DGRAM, 0);

if (-1 == sockfd)

{

printf("socket open err.");

return -1;

}

// 2. 准备接收方的地址和端口,'192.168.0.107'表示目的ip地址,8266表示目的端口号

struct sockaddr_in sock_addr = {0};

sock_addr.sin_family = AF_INET; // 设置地址族为IPv4

sock_addr.sin_port = htons(8266); // 设置地址的端口号信息

sock_addr.sin_addr.s_addr = inet_addr("192.168.0.107"); // 设置IP地址

// 3. 发送数据到指定的ip和端口

char sendbuf[]={"hello world, I am UDP."};

int cnt = 10;

while(cnt--)

{

ret = sendto(sockfd, sendbuf, sizeof(sendbuf), 0, (struct sockaddr*)&sock_addr, sizeof(sock_addr));

printf("ret = %d \n",ret);

sleep(1);

}

// 4. 关闭套接字

close(sockfd);

}

三、UDP接收数据

在之前发送数据的时候,我们可以看到,其端口号是一直在变得,那么我们要接收数据,就需要知道其端口号是什么,所以我们要先固定一个端口号,使用bind函数

// 2、绑定本地的相关信息,如果不绑定,则系统会随机分配一个端口号

struct sockaddr_in local_addr = {0};

local_addr.sin_family = AF_INET; //使用IPv4地址

local_addr.sin_addr.s_addr = inet_addr("192.168.0.107"); //本机IP地址

local_addr.sin_port = htons(12341); //端口

bind(sockfd, (struct sockaddr*)&local_addr, sizeof(local_addr));//将套接字和IP、端口绑定

接收数据使用recvfrom函数,第一个参数位socket 文件描述符,第二个参数为接收缓冲区,第三参数为最大接收数据长度,第四个参数一般为零,第五个参数为发送来数据的对方的地址及端口信息;

// 3、等待接收对方发送的数据

struct sockaddr_in recv_addr;

socklen_t addrlen = sizeof(recv_addr);

char recvbuf[1024] = {0};

ret = recvfrom(sockfd, recvbuf, 1024, 0,(struct sockaddr*)&recv_addr,&addrlen); //1024表示本次接收的最大字节数

接收完后将其打印出来:

printf("[recv from %s:%d]%s \n",inet_ntoa(*(struct in_addr*)&recv_addr.sin_addr.s_addr),ntohs(recv_addr.sin_port),recvbuf);

运行结果: 贴上完整代码:

#include

#include

#include

#include

#include

#include

int main(void)

{

int ret = -1;

// 1、使用socket()函数获取一个socket文件描述符

int sockfd = socket(AF_INET, SOCK_DGRAM, 0);

if (-1 == sockfd)

{

printf("socket open err.");

return -1;

}

// 2、绑定本地的相关信息,如果不绑定,则系统会随机分配一个端口号

struct sockaddr_in local_addr = {0};

local_addr.sin_family = AF_INET; //使用IPv4地址

local_addr.sin_addr.s_addr = inet_addr("192.168.0.107"); //本机IP地址

local_addr.sin_port = htons(12341); //端口

bind(sockfd, (struct sockaddr*)&local_addr, sizeof(local_addr));//将套接字和IP、端口绑定

// 3、等待接收对方发送的数据

struct sockaddr_in recv_addr;

socklen_t addrlen = sizeof(recv_addr);

char recvbuf[1024] = {0};

ret = recvfrom(sockfd, recvbuf, 1024, 0,(struct sockaddr*)&recv_addr,&addrlen); //1024表示本次接收的最大字节数

printf("[recv from %s:%d]%s \n",inet_ntoa(*(struct in_addr*)&recv_addr.sin_addr.s_addr),ntohs(recv_addr.sin_port),recvbuf);

// 4. 关闭套接字

close(sockfd);

}

四、UDP收发数据

实现这样一个功能,通过UDP发送10次消息,然后等待接收,将接收的数据及其来源打印出来: 完成代码:

#include

#include

#include

#include

#include

#include

int main(void)

{

int ret = -1;

// 1、使用socket()函数获取一个socket文件描述符

int sockfd = socket(AF_INET, SOCK_DGRAM, 0);

if (-1 == sockfd)

{

printf("socket open err.");

return -1;

}

// 2、绑定本地的相关信息,如果不绑定,则系统会随机分配一个端口号

struct sockaddr_in local_addr = {0};

local_addr.sin_family = AF_INET; //使用IPv4地址

local_addr.sin_addr.s_addr = inet_addr("192.168.0.107"); //本机IP地址

local_addr.sin_port = htons(12341); //端口

bind(sockfd, (struct sockaddr*)&local_addr, sizeof(local_addr));//将套接字和IP、端口绑定

// 3. 发送数据到指定的ip和端口,'192.168.0.107'表示目的ip地址,8266表示目的端口号

struct sockaddr_in sock_addr = {0};

sock_addr.sin_family = AF_INET; // 设置地址族为IPv4

sock_addr.sin_port = htons(8266); // 设置地址的端口号信息

sock_addr.sin_addr.s_addr = inet_addr("192.168.0.107"); // 设置IP地址

char sendbuf[]={"hello world, I am a UDP socket."};

int cnt = 10;

while(cnt--)

{

ret = sendto(sockfd, sendbuf, sizeof(sendbuf)-1, 0, (struct sockaddr*)&sock_addr, sizeof(sock_addr));

//printf("ret = %d \n",ret);

sleep(1);

}

// 4、等待接收对方发送的数据

struct sockaddr_in recv_addr;

socklen_t addrlen = sizeof(recv_addr);

char recvbuf[1024] = {0};

while(1)

{

ret = recvfrom(sockfd, recvbuf, 1024, 0,(struct sockaddr*)&recv_addr,&addrlen); //1024表示本次接收的最大字节数

printf("[recv from %s:%d]%s \n",inet_ntoa(*(struct in_addr*)&recv_addr.sin_addr.s_addr),ntohs(recv_addr.sin_port),recvbuf);

}

// 5. 关闭套接字

close(sockfd);

}

五、同时收发数据

现在实现这样一个功能,即运行程序,然后将我输入的字符串发送出去的同时,还可以接收数据,我使用多线程来实现这个程序,不过要实现方便接收,我们在程序的开始,将IP地址和端口号打印出来,实现效果如下: 实现代码:注意:因为pthread并非Linux系统的默认库,而是POSIX线程库。在Linux中将其作为一个库来使用,因此加上 -lpthread(或-pthread)以显式链接该库。

#include

#include

#include

#include

#include

#include

#include

void *recv_thread(void *arg)

{

int socket_fd = *(int *)arg;

struct sockaddr_in recv_addr;

socklen_t addrlen = sizeof(recv_addr);

char recvbuf[1024] = {0};

while(1)

{

recvfrom(socket_fd, recvbuf, 1024, 0,(struct sockaddr*)&recv_addr,&addrlen); //1024表示本次接收的最大字节数

printf("[recv from %s:%d]%s \n",inet_ntoa(*(struct in_addr*)&recv_addr.sin_addr.s_addr),ntohs(recv_addr.sin_port),recvbuf);

}

}

int main(void)

{

int ret = -1;

pthread_t th = -1;

// 1、使用socket()函数获取一个socket文件描述符

int sockfd = socket(AF_INET, SOCK_DGRAM, 0);

if (-1 == sockfd)

{

printf("socket open err.");

return -1;

}

// 2、绑定本地的相关信息,如果不绑定,则系统会随机分配一个端口号

struct sockaddr_in local_addr = {0};

local_addr.sin_family = AF_INET; //使用IPv4地址

local_addr.sin_addr.s_addr = inet_addr("192.168.0.107"); //本机IP地址

local_addr.sin_port = htons(12341); //端口

bind(sockfd, (struct sockaddr*)&local_addr, sizeof(local_addr));//将套接字和IP、端口绑定

// 3、打印本机ip地址和端口号

printf("local ipaddr and port->192.168.0.107:12341\n");

// 4、创建一个线程,用来接收数据

ret = pthread_create(&th, NULL, recv_thread, &sockfd);

// 5、等待输入数据,然后发送出去,直到输入的数据为'quit','192.168.0.107'表示目的ip地址,8266表示目的端口号

struct sockaddr_in sock_addr = {0};

sock_addr.sin_family = AF_INET; // 设置地址族为IPv4

sock_addr.sin_port = htons(8266); // 设置地址的端口号信息

sock_addr.sin_addr.s_addr = inet_addr("192.168.0.107"); // 设置IP地址

char sendbuf[1024]={"hello world, I am a UDP socket."};

int cnt = 10;

while(cnt--)

{

printf("please input a string.input 'quit' to quit.\n");

scanf("%s",sendbuf);

if(strcmp(sendbuf,"quit") == 0)

break;

sendto(sockfd, sendbuf, strlen(sendbuf), 0, (struct sockaddr*)&sock_addr, sizeof(sock_addr));

}

// 6. 关闭套接字

close(sockfd);

}

Willliam_william

优惠劵

诗筱涵

关注

关注

21

点赞

106

收藏

觉得还不错?

一键收藏

知道了

0

评论

C语言网络编程(1)— UDP通信(这篇写得很详细,也讲了怎么借助网络调试助手)

这篇写得很详细,也讲了怎么借助网络调试助手转载自:https://blog.csdn.net/qq_38113006/article/details/105531439C语言网络编程(1)— UDP通信Willliam_william 2020-04-15 13:56:37 1465 收藏 22 分类专栏: C语言网络编程版权C语言网络编程(1)— UDP通信一、socket我们要进行网络通信,那么就要用到socket,socket即网络套接字,应用程序可以通过它发送或接收

复制链接

扫一扫

专栏目录

宋劲彬的嵌入式C语言一站式编程

03-12

目录

历史

前言

I. C语言入门

1. 程序的基本概念

1. 程序和编程语言

2. 自然语言和形式语言

3. 程序的调试

4. 第一个程序

2. 常量、变量和表达式

1. 继续Hello World

2. 常量

3. 变量

4. 赋值

5. 表达式

6. 字符类型与字符编码

3. 简单函数

1. 数学函数

2. 自定义函数

3. 形参和实参

4. 全局变量、局部变量和作用域

4. 分支语句

1. if语句

2. if/else语句

3. 布尔代数

4. switch语句

5. 深入理解函数

1. return语句

2. 增量式开发

3. 递归

6. 循环语句

1. while语句

2. do/while语句

3. for语句

4. break和continue语句

5. 嵌套循环

6. goto语句和标号

7. 结构体

1. 复合类型与结构体

2. 数据抽象

3. 数据类型标志

4. 嵌套结构体

8. 数组

1. 数组的基本概念

2. 数组应用实例:统计随机数

3. 数组应用实例:直方图

4. 字符串

5. 多维数组

9. 编码风格

1. 缩进和空白

2. 注释

3. 标识符命名

4. 函数

5. indent工具

10. gdb

1. 单步执行和跟踪函数调用

2. 断点

3. 观察点

4. 段错误

11. 排序与查找

1. 算法的概念

2. 插入排序

3. 算法的时间复杂度分析

4. 归并排序

5. 线性查找

6. 折半查找

12. 栈与队列

1. 数据结构的概念

2. 堆栈

3. 深度优先搜索

4. 队列与广度优先搜索

5. 环形队列

13. 本阶段总结

II. C语言本质

14. 计算机中数的表示

1. 为什么计算机用二进制计数

2. 不同进制之间的换算

3. 整数的加减运算

3.1. Sign and Magnitude表示法

3.2. 1's Complement表示法

3.3. 2's Complement表示法

3.4. 有符号数和无符号数

4. 浮点数

15. 数据类型详解

1. 整型

2. 浮点型

3. 类型转换

3.1. Integer Promotion

3.2. Usual Arithmetic Conversion

3.3. 由赋值产生的类型转换

3.4. 强制类型转换

3.5. 编译器如何处理类型转换

16. 运算符详解

1. 位运算

1.1. 按位与、或、异或、取反运算

1.2. 移位运算

1.3. 掩码

1.4. 异或运算的一些特性

2. 其它运算符

2.1. 复合赋值运算符

2.2. 条件运算符

2.3. 逗号运算符

2.4. sizeof运算符与typedef类型声明

3. Side Effect与Sequence Point

4. 运算符总结

17. 计算机体系结构基础

1. 内存与地址

2. CPU

3. 设备

4. MMU

5. Memory Hierarchy

18. x86汇编程序基础

1. 最简单的汇编程序

2. x86的寄存器

3. 第二个汇编程序

4. 寻址方式

5. ELF文件

5.1. 目标文件

5.2. 可执行文件

19. 汇编与C之间的关系

1. 函数调用

2. main函数和启动例程

3. 变量的存储布局

4. 结构体和联合体

5. C内联汇编

6. volatile限定符

20. 链接详解

1. 多目标文件的链接

2. 定义和声明

2.1. extern和static关键字

2.2. 头文件

2.3. 定义和声明的详细规则

3. 静态库

4. 共享库

4.1. 编译、链接、运行

4.2. 动态链接的过程

4.3. 共享库的命名惯例

5. 虚拟内存管理

21. 预处理

1. 预处理的步骤

2. 宏定义

2.1. 函数式宏定义

2.2. 内联函数

2.3. #、##运算符和可变参数

2.4. 宏展开的步骤

3. 条件预处理指示

4. 其它预处理特性

22. Makefile基础

1. 基本规则

2. 隐含规则和模式规则

3. 变量

4. 自动处理头文件的依赖关系

5. 常用的make命令行选项

23. 指针

1. 指针的基本概念

2. 指针类型的参数和返回值

3. 指针与数组

4. 指针与const限定符

5. 指针与结构体

6. 指向指针的指针与指针数组

7. 指向数组的指针与多维数组

8. 函数类型和函数指针类型

9. 不完全类型和复杂声明

24. 函数接口

1. 本章的预备知识

1.1. strcpy与strncpy

1.2. malloc与free

2. 传入参数与传出参数

3. 两层指针的参数

4. 返回值是指针的情况

5. 回调函数

6. 可变参数

25. C标准库

1. 字符串操作函数

1.1. 初始化字符串

1.2. 取字符串的长度

1.3. 拷贝字符串

1.4. 连接字符串

1.5. 比较字符串

1.6. 搜索字符串

1.7. 分割字符串

2. 标准I/O库函数

2.1. 文件的基本概念

2.2. fopen/fclose

2.3. stdin/stdout/stderr

2.4. errno与perror函数

2.5. 以字节为单位的I/O函数

2.6. 操作读写位置的函数

2.7. 以字符串为单位的I/O函数

2.8. 以记录为单位的I/O函数

2.9. 格式化I/O函数

2.10. C标准库的I/O缓冲区

2.11. 本节综合练习

3. 数值字符串转换函数

4. 分配内存的函数

26. 链表、二叉树和哈希表

1. 链表

1.1. 单链表

1.2. 双向链表

1.3. 静态链表

1.4. 本节综合练习

2. 二叉树

2.1. 二叉树的基本概念

2.2. 排序二叉树

3. 哈希表

27. 本阶段总结

III. Linux系统编程

28. 文件与I/O

1. 汇编程序的Hello world

2. C标准I/O库函数与Unbuffered I/O函数

3. open/close

4. read/write

5. lseek

6. fcntl

7. ioctl

8. mmap

29. 文件系统

1. 引言

2. ext2文件系统

2.1. 总体存储布局

2.2. 实例剖析

2.3. 数据块寻址

2.4. 文件和目录操作的系统函数

3. VFS

3.1. 内核数据结构

3.2. dup和dup2函数

30. 进程

1. 引言

2. 环境变量

3. 进程控制

3.1. fork函数

3.2. exec函数

3.3. wait和waitpid函数

4. 进程间通信

4.1. 管道

4.2. 其它IPC机制

5. 练习:实现简单的Shell

31. Shell脚本

1. Shell的历史

2. Shell如何执行命令

2.1. 执行交互式命令

2.2. 执行脚本

3. Shell的基本语法

3.1. 变量

3.2. 文件名代换(Globbing):* ? []

3.3. 命令代换:`或 $()

3.4. 算术代换:$(())

3.5. 转义字符\

3.6. 单引号

3.7. 双引号

4. bash启动脚本

4.1. 作为交互登录Shell启动,或者使用--login参数启动

4.2. 以交互非登录Shell启动

4.3. 非交互启动

4.4. 以sh命令启动

5. Shell脚本语法

5.1. 条件测试:test [

5.2. if/then/elif/else/fi

5.3. case/esac

5.4. for/do/done

5.5. while/do/done

5.6. 位置参数和特殊变量

5.7. 函数

6. Shell脚本的调试方法

32. 正则表达式

1. 引言

2. 基本语法

3. sed

4. awk

5. 练习:在C语言中使用正则表达式

33. 信号

1. 信号的基本概念

2. 产生信号

2.1. 通过终端按键产生信号

2.2. 调用系统函数向进程发信号

2.3. 由软件条件产生信号

3. 阻塞信号

3.1. 信号在内核中的表示

3.2. 信号集操作函数

3.3. sigprocmask

3.4. sigpending

4. 捕捉信号

4.1. 内核如何实现信号的捕捉

4.2. sigaction

4.3. pause

4.4. 可重入函数

4.5. sig_atomic_t类型与volatile限定符

4.6. 竞态条件与sigsuspend函数

4.7. 关于SIGCHLD信号

34. 终端、作业控制与守护进程

1. 终端

1.1. 终端的基本概念

1.2. 终端登录过程

1.3. 网络登录过程

2. 作业控制

2.1. Session与进程组

2.2. 与作业控制有关的信号

3. 守护进程

35. 线程

1. 线程的概念

2. 线程控制

2.1. 创建线程

2.2. 终止线程

3. 线程间同步

3.1. mutex

3.2. Condition Variable

3.3. Semaphore

3.4. 其它线程间同步机制

4. 编程练习

36. TCP/IP协议基础

1. TCP/IP协议栈与数据包封装

2. 以太网(RFC 894)帧格式

3. ARP数据报格式

4. IP数据报格式

5. IP地址与路由

6. UDP段格式

7. TCP协议

7.1. 段格式

7.2. 通讯时序

7.3. 流量控制

37. socket编程

1. 预备知识

1.1. 网络字节序

1.2. socket地址的数据类型及相关函数

2. 基于TCP协议的网络程序

2.1. 最简单的TCP网络程序

2.2. 错误处理与读写控制

2.3. 把client改为交互式输入

2.4. 使用fork并发处理多个client的请求

2.5. setsockopt

2.6. 使用select

3. 基于UDP协议的网络程序

4. UNIX Domain Socket IPC

5. 练习:实现简单的Web服务器

5.1. 基本HTTP协议

5.2. 执行CGI程序

A. 字符编码

1. ASCII码

2. Unicode和UTF-8

3. 在Linux C编程中使用Unicode和UTF-8

B. GNU Free Documentation License Version 1.3, 3 November 2008

参考书目

索引

C语言实现--基于UDP的多人在线聊天室

m0_68210771的博客

10-13

2243

基于UDP协议,完成一个功能比较完善的在线的聊天室项目,该项目涉及到的知识主要有C语言,数据结构,网络编程,进程等。

参与评论

您还未登录,请先

登录

后发表或查看评论

C 语言实现 UDP

Zlb2214的博客

11-14

701

发送广播信息,局域网中的客户端都可以接受该信息客户端接收广播信息,防火墙可能会影响广播的信息发送。1。

LabVIEW高级编程与虚拟仪器工程应用

07-28

《LabVIEW高级编程与虚拟仪器工程应用(修订版)》适用有一定LabVIEW编程基础的测控工程技术人员,帮助其搭建高级技术框架,积累开发经验;同时也可作为本科生毕业设计、研究生完成课题和工程技术人员开发测控项目的参考用书。

目录

第1篇LabVIEW高级编程技术

第1章测控项目管理

1.1测控项目的生命周期

1.2系统定义

1.2.1 问题定义

1.2.2可行性研究

1.2.3 需求分析

1.2.4软件原型

1.2.5 文档管理

1.3总体设计

1.3.1硬件结构设计

1.3.2软件结构设计

1.3.3 总体设计说明书

1.4详细设计

1.5程序编码

1.5.1编程风格

1.5.2说明信息

1.5.3 vl的保存

1.5.4手册编写

1.6系统测试

1.6.1硬件测试

1.6.2软件测试

1.6.3验收测试

1.6.4测试报告

1.7 系统维护

1.8 项目浏览器

1.8.1 项目浏览器的用途

1.8.2 项目库

1.8.3项目依赖关系

1.8.4程序生成规范

第2章应用程序控制与内部数据传递

2.1 VI Server技术简介

2.2动态加载VI

2.2.1监测内存中所有的VI

2.2.2 动态加载VI的程序

2.3动态控制VI运行

2.3.1 动态刷新被控VI前面板控件值

2.3.2选择性打开VI前面板

2.3.3子面板设计

2 4动态控制VI属性和前面板对象属性

2.4.1 动态控制VI属性

2.4.2动态控制前面板对象属性

2.5动态注册事件

2.5.1 动态注册用户接口事件

2.5.2处理用户事件

2.6运行菜单控制

2.6.1运行菜单的设置

2.6.2用程序代码进行运行菜单设置

2.6.3在程序中响应菜单选项

2 7通知器和队列

2.7.1 通知器

2.7.2 队列

2 R共享变量

2.8.1共享变量的创建

2.8.2单进程共享变量

2.8.3 网络发布共享变量

第3章程序设计模式与程序性能

3.1 程序的设计模式

3.1.1标准状态机

3.1.2主/从设计模式

3.1.3 生产者/消费者设计模式

3.1.4队列消息处理器

3.1.5其他设计模式

3.2程序调试技巧

3.3多线程程序

3.3.1基本定义

3.3.2 多线程应用程序的优势

3.3.3 LabVIEW实现多线程的方法

3.4程序性能优化

3.4.1程序运行速度

3.4.2 内存使用

3.5程序性能分析

第4章软件接口与外部数据通信

4.1 ActiveX技术应用

4.1.1 ActiveX技术简介

4.1.2使用ActiveX控件

4.1.3使用ActiveX自动化

4.1.4 LabVIEW作为ActiveX服务器

4.2.NET技术应用

4.2.1.NET技术简介

4.2.2 .NET技术应用

4.3动态数据交换

4.3.1 LabVIEW的DDE功能

4.3.2向Excel文件写数据

4.3.3 由Excel文件读数据

4.4 C代码调用

4.5库函数调用

4.6执行操作系统命令

4.7计算机网络基础知识

4.7.1 计算机网络的功能与发展

4.7.2计算机网络的结构

4.7.3 计算机网络模型

4.7.4计算机网络协议

4.8 TCP 应用

4.8.1发送数据编程

4.8.2接收数据编程

4.8.3程序的远程动态控制

4.9 UDP应用

4.10 串口通信

第5章数据存储与调用

5.1数据存储的时机

5.2打印报表

5.3数据库连接

5.3.1 LabVIEW与数据库的连接

5.3.2 LabVIEW对Access数据库的操作

5.3.3 LabVIEW对SQL Server数据库的操作

5.4 LabVIEW与实时数据库连接

第6章面向对象编程

6.1面向对象编程的概念

6.2 LabVIEW中面向对象编程的方法

6 2.1 LabVIEW类

6.2.2类的方法

6.2.3继承

6.3两种编程方法的比较

6.3.1测试目的

6.3.2面向过程的方法

6.3.3 面向对象的方法

6.3.4 两种方法的比较

第7章传统DAQ的模拟信号采集

7.1 硬件配置与测试

7.1.1传统DAQ安装

7.1.2传统DAQ设备配置与测试

7.2模拟输入

7.2.1传统DAQ的数据采集通道

7.2.2数据采集Vl

7.2.3传统DAQ模拟输入常用的基本术语

7.2.4测量直流电压信号

7.2.5 波形采集

7.2.6频率测量

7.3模拟输出

7.3.1输出直流信号

7.3.2输出波形信号

7.3.3 模拟输入/输出控制回路

7.4信号调理

7.4.1信号调理设备配置

7.4.2应变测量

7.4.3温度测量

第8章传统DAQ的数字信号与计数器输入/输出

8.1 数字信号输入/输出

8.1.1数字信号通道设置

8.1.2立即方式数字输入/输出

8.1.3握手方式数字输入/输出

8.2计数器输入/输出

8.2.1数据采集卡的计数器芯片

8.2.2 用计数器输出脉冲信号

8.2.3测量脉冲宽度

8.2.4测量TTL信号频率和周期

8.2.5事件计数与计时

第2篇虚拟仪器工程案例篇

第3篇C语言代码转换和LabVIEW2010新特性篇

LabVIEW常用中英文词汇对照表

参考文献

unix平台下c语言高级编程指南

09-26

内容简介回到顶部↑

本书是专为在UNIX平台下用C语言编制程序的人写的。是以POSIX为标准,主要以C语言为基础,详细介绍了UNIX平台下编写各种应用程序的范例和方法。全书分四个部分,共十五章。本书范例丰富,且具有代表性,如Socket编程、客户/服务端编程、多线程开发、CGI编程、X Windows下的Motif编程等。读者直接或只需稍作修改就可以将它们应用到自己的应用程序开发中。这些范例的源代码可以从配套光盘的电子书中直接拷贝使用。

目录回到顶部↑

第一部分 基本的系统调用

第1章 文件子系统

1.1 文件子系统的基本概念

1.2 基本的文件输入和输出

1.3 高级的文件操作

第2章 终端操作

2.1 终端的基本概念

2.2 终端输入和输出

2.3 ioctl系统调用

第3章 进程及进程间通信

3.1 进程的基本概念

3.2 进程的一般操作

3.3 进程的特殊操作

3.4 进程间使用管道通信

第4章 信号

4.1 信号的基本概念

4.2 信号机制

4.3 有关信号的系统调用

第5章 部分其他调用

5.1 系统调用

.5.2 相关函数

第二部分 网络编程

第6章 Socket编程基础

6.1 TCP/IP基础知识

6.2 Socket一般描述

6.3 Socket中的主要调用

6.4 Socket的原始方式

第7章 客户/服务器编程

7.1 客户端程序设计

7.2 服务器端程序设计

7.3 服务端程序结构

7.4 多协议(TCP、UDP)服务端

7.5 客户端的并发程序设计

7.6 使用telnet协议的客户端例子

第8章 线程

8.1 有关线程的基本概念

8.2 线程的创建和终止

8.3 线程控制调用

8.4 线程之间的互斥

8.5 线程之间的同步

8.6 线程特定数据区的函数调用

8.7 一个使用线程的客户端并发的例子

8.8 有关线程的函数列表

第9章 CGl编程

9.1 CGI程序的基本概念

9.2 CGI基本编程

9.3 使用脚本语言编写CGl

9.4 Perl语言简介

9.5 一个简单的CGI例子

第三部分 X Window应用程序开发

第10章 X Window和Motif基础

10.1 简介

10.2 XWindow基本概念

10.3 启动Motif窗口管理器

10.4 设置Motif特性

10.5 Widget

第11章 Motif编程

11.1 基本编程概念

11.2 Widget资源

11.3 Motif编程基础

11.4 程序框架

11.5 "HelloWorld!"示例

11.6 管理器

11.7 按钮

11.8 X事件

11.9 其他Widget简介

11.10 菜单

11.11 对话框

第12章 Widget与X事件汇总

12.1 Widget

12.2 X事件

第四部分 常用的编程工具

第13章 编译器及调试工具

13.1 编译器用法入门

13.2 调试器使用入门

13.3 关于库的简介

第14章 Make工具及makefile规则

14.1 概述

14.2 make和makefile的关系

14.3 makefile规则

14.4 伪指令

14.5 make命令行参数

第15章 版本控制

15.1 版本控制概念

15.2 源代码控制系统SCCS

15.3 RCS使用方法

15.4 并发版本控制CVS

关于c语言的udp通讯详细讲解

sakura0908的博客

03-17

5391

UDP全称 User Datagram Protocol,即:用户数据报协议。是面向无连接的协议。通常,UDP 通信还会被冠以不可靠的头衔。这里的不可靠指的是:无法可靠地得知对方是否收到数据。

C语言实现UDP通信

qq_44423388的博客

04-15

1万+

UDP通信

UDP是一种无连接的尽最大努力交付的不可靠连接,通信之前无需先建立连接,自然而然,通信之后也就无需再释放连接。

通信的套接字

UDP所采用的通信接口与前面讲过的TCP通信接口相同,只是没有建立连接这一步。

socket()用来创建套接字,使用 udp 协议时,选择数据报服务 SOCK_DGRAM。sendto()用来发送数据,由于 UDP 是无连接的,每次发送数据都需要指定对端的地址(IP 和端口)。recvfrom()接收数据,每次都需要传给该方法一个地址结构来存放发送端的地址。

recvfr

基于C语言的UDP聊天室项目——网络编程(含源码)

m0_65821435的博客

03-27

1559

利用UDP协议,实现一套聊天室软件。服务器端记录客户端的地址,客户端发送消息后,服务器群发给各个客户端软件。

基于(LinuxC语言)的UDP局域网聊天室

weixin_45870919的博客

01-20

1276

基于(LinuxC语言)的udp局域网聊天室

c实现 udp通信

xiaobbinm的博客

08-27

2458

udp通信

Android C++高级编程:使用NDK_Onur Cinar, 于红PDF电子书下载 带书签目录 完整版

11-06

Android C++高级编程:使用NDK_Onur Cinar, 于红PDF电子书下载 带书签目录 完整版

原书名:Pro Android C++ with the NDK

原出版社: Apress

作者: (美)Onur Cinar

译者: 于红 佘建伟 冯艳红

丛书名: 移动开发经典丛书

出版社:清华大学出版社

ISBN:9787302343011

上架时间:2013-12-30

出版日期:2014 年1月

开本:16开

页码:344

版次:1-1

第1章 Android平台上的C++入门 1

1.1 Microsoft Windows 1

1.1.1 在Windows平台上下载并安装JDK开发包 2

1.1.2 在Windows平台上下载并安装Apache ANT 5

1.1.3 在Windows平台上下载并安装Android SDK 7

1.1.4 在Windows平台上下载并安装Cygwin 8

1.1.5 在Windows平台上下载并安装Android NDK 11

1.1.6 在Windows平台上下载并安装Eclipse 13

1.2 Apple Mac OS X 14

1.2.1 在Mac平台上安装Xcode 14

1.2.2 验证Mac平台的Java开发包 15

1.2.3 验证Mac平台上的Apache ANT 15

1.2.4 验证GNU Make 16

1.2.5 在Mac平台上下载并安装Android SDK 16

1.2.6 在Mac平台上下载并安装Android NDK 18

1.2.7 在Mac平台上下载并安装Eclipse 19

1.3 Ubuntu Linux 20

1.3.1 检查GNU C库版本 20

1.3.2 激活在64位系统上支持32位的功能 21

1.3.3 在Linux平台上下载并安装Java开发工具包(JDK) 21

1.3.4 在Linux平台上下载并安装Apache ANT 22

1.3.5 在Linux平台上下载并安装GNU Make 22

1.3.6 在Linux平台上下载并安装Android SDK 23

1.3.7 在Linux平台上下载并安装Android NDK 24

1.3.8 在Linux平台上下载并安装Eclipse 25

1.4 下载并安装ADT 26

1.4.1 安装Android平台包 29

1.4.2 配置模拟器 30

1.5 小结 33

第2章 深入了解Android NDK 35

2.1 Android NDK提供的组件 35

2.2 Android NDK的结构 36

2.3 以一个示例开始 36

2.3.1 指定Android NDK的位置 37

2.3.2 导入示例项目 37

2.3.3 向项目中添加原生支持 39

2.3.4 运行项目 40

2.3.5 用命令行对项目进行构建 41

2.3.6 检测Android NDK项目的结构 42

2.4 构建系统 42

2.4.1 Android.mk 43

2.4.2 Application.mk 53

2.5 使用NDK-Build脚本 54

2.6 排除构建系统故障 55

2.7 小结 56

第3章 用JNI实现与原生代码通信 57

3.1 什么是JNI 57

3.2 以一个示例开始 57

3.2.1 原生方法的声明 58

3.2.2 加载共享库 58

3.2.3 实现原生方法 59

3.3 数据类型 64

3.3.1 基本数据类型 64

3.3.2 引用类型 64

3.4 对引用数据类型的操作 65

3.4.1 字符串操作 65

3.4.2 数组操作 67

3.4.3 NIO 操作 68

3.4.4 访问域 69

3.4.5 调用方法 71

3.4.6 域和方法描述符 72

3.5 异常处理 75

3.5.1 捕获异常 75

3.5.2 抛出异常 75

3.6 局部和全局引用 76

3.6.1 局部引用 76

3.6.2 全局引用 76

3.6.3 弱全局引用 77

3.7 线程 78

3.7.1 同步 78

3.7.2 原生线程 79

3.8 小结 79

第4章 使用SWIG自动生成JNI代码 81

4.1 什么是SWIG 81

4.2 安装 82

4.2.1 Windows平台上SWIG的安装 82

4.2.2 在Mac OS X下安装 83

4.2.3 在Ubuntu Linux下安装 85

4.3 通过示例程序试用SWIG 86

4.3.1 接口文件 86

4.3.2 在命令行方式下调用SWIG 89

4.3.3 将SWIG集成到Android构建过程中 90

4.3.4 更新Activity 92

4.3.5 执行应用程序 93

4.3.6 剖析生成的代码 93

4.4 封装C语言代码 94

4.4.1 全局变量 94

4.4.2 常量 95

4.4.3 只读变量 96

4.4.4 枚举 97

4.4.5 结构体 100

4.4.6 指针 101

4.5 封装C++代码 101

4.5.1 指针、引用和值 102

4.5.2 默认参数 103

4.5.3 重载函数 104

4.5.4 类 104

4.6 异常处理 106

4.7 内存管理 107

4.8 从原生代码中调用Java 108

4.8.1 异步通信 108

4.8.2 启用Directors 109

4.8.3 启用RTTI 109

4.8.4 重写回调方法 109

4.8.5 更新HelloJni Activity 110

4.9 小结 110

第5章 日志、调试及故障处理 111

5.1 日志 111

5.1.1 框架 111

5.1.2 原生日志API 112

5.1.3 受控制的日志 114

5.1.4 控制台日志 118

5.2 调试 119

5.2.1 预备知识 119

5.2.2 调试会话建立 120

5.2.3 建立调试示例 121

5.2.4 启动调试器 121

5.3 故障处理 126

5.3.1 堆栈跟踪分析 127

5.3.2 对JNI的扩展检查 128

5.3.3 内存问题 130

5.3.4 strace 133

5.4 小结 134

第6章 Bionic API入门 135

6.1 回顾标准库 135

6.2 还有另一个C库 136

6.2.1 二进制兼容性 136

6.2.2 提供了什么 136

6.2.3 缺什么 137

6.3 内存管理 137

6.3.1 内存分配 137

6.3.2 C语言的动态内存管理 138

6.3.3 C++的动态内存管理 139

6.4 标准文件I/O 141

6.4.1 标准流 141

6.4.2 使用流I/O 141

6.4.3 打开流 142

6.4.4 写入流 143

6.4.5 流的读取 145

6.4.6 搜索位置 148

6.4.7 错误检查 149

6.4.8 关闭流 149

6.5 与进程交互 150

6.5.1 执行shell命令 150

6.5.2 与子进程通信 150

6.6 系统配置 151

6.6.1 通过名称获取系统属性值 152

6.6.2 通过名称获取系统属性 152

6.7 用户和组 153

6.7.1 获取应用程序用户和组ID 153

6.7.2 获取应用程序用户名 154

6.8 进程间通信 154

6.9 小结 154

第7章 原生线程 155

7.1 创建线程示例项目 155

7.1.1 创建Android项目 155

7.1.2 添加原生支持 157

7.1.3 声明字符串资源 157

7.1.4 创建简单的用户界面 157

7.1.5 实现Main Activity 159

7.1.6 生成C/C++头文件 162

7.1.7 实现原生函数 163

7.1.8 更新Android.mk构建脚本 165

7.2 Java 线程 165

7.2.1 修改示例应用程序使之能够使用Java线程 165

7.2.2 执行Java Threads示例 166

7.2.3 原生代码使用Java线程的优缺点 167

7.3 POSIX线程 168

7.3.1 在原生代码中使用POSIX线程 168

7.3.2 用pthread_create创建线程 168

7.3.3 更新示例应用程序以使用POSIX线程 169

7.3.4 执行POSIX线程示例 174

7.4 从POSIX线程返回结果 174

7.5 POSIX线程同步 176

7.5.1 用互斥锁同步POSIX线程 176

7.5.2 使用信号量同步POSIX线程 180

7.6 POSIX线程的优先级和调度策略 180

7.6.1 POSIX的线程调度策略 181

7.6.2 POSIX Thread优先级 181

7.7 小结 181

第8章 POSIX Socket API:面向连接的通信 183

8.1 Echo Socket示例应用 183

8.1.1 Echo Android应用项目 184

8.1.2 抽象echo activity 184

8.1.3 echo应用程序字符串资源 188

8.1.4 原生echo模块 188

8.2 用TCP sockets实现面向连接的通信 191

8.2.1 Echo Server Activity的布局 192

8.2.2 Echo Server Activity 193

8.2.3 实现原生TCP Server 194

8.2.4 Echo客户端Activity布局 206

8.2.5 Echo客户端Activity 208

8.2.6 实现原生TCP客户端 210

8.2.7 更新Android Manifest 213

8.2.8 运行TCP Sockets示例 214

8.3 小结 217

第9章 POSIX Socket API:无连接的通信 219

9.1 将UDP Server方法添加到Echo Server Activity中 219

9.2 实现原生UDP Server 220

9.2.1 创建UDP Socket:socket 220

9.2.2 从Socket接收数据报:recvfrom 221

9.2.3 向Socket发送数据报:sendto 223

9.2.4 原生UDP Server方法 224

9.3 将原生UDP Client方法加入Echo Client Activity中 225

9.4 实现原生UDP Client 226

9.5 运行UDP Sockets示例 228

9.5.1 连通UDP的模拟器 228

9.5.2 启动Echo UDP Client 229

9.6 小结 229

第10章 POSIX Socket API:本地通信 231

10.1 Echo Local Activity布局 231

10.2 Echo Local Activity 232

10.3 实现原生本地Socket Server 237

10.3.1 创建本地Socket:socket 237

10.3.2 将本地socket与Name绑定:bind 238

10.3.3 接受本地Socket:accept 240

10.3.4 原生本地Socket Server 240

10.4 将本地Echo Activity添加到Manifest中 242

10.5 运行本地 Sockets示例 243

10.6 异步I/O 243

10.7 小结 244

第11章 支持C++ 245

11.1 支持的C++运行库 245

11.1.1 GAbi++ C++运行库 246

11.1.2 STLport C++运行库 246

11.1.3 GNU STL C++运行库 246

11.2 指定C++运行库 246

11.3 静态运行库与动态运行库 247

11.4 C++异常支持 247

11.5 C++ RTTI支持 248

11.6 C++标准库入门 249

11.6.1 容器 249

11.6.2 迭代器 250

11.6.3 算法 251

11.7 C++运行库的线程安全 251

11.8 C++运行库调试模式 251

11.8.1 GNU STL调试模式 251

11.8.2 STLport调试模式 252

11.9 小结 253

第12章 原生图形API 255

12.1 原生图形API的可用性 255

12.2 创建一个AVI视频播放器 256

12.2.1 将AVILib作为NDK的一个导入模块 256

12.2.2 创建AVI播放器Android应用程序 258

12.2.3 创建AVI Player的Main Activity 258

12.2.4 创建Abstract Player Activity 262

12.3 使用JNI图形API进行渲染 269

12.3.1 启用JNI Graphics API 269

12.3.2 使用JNI Graphics API 270

12.3.3 用Bitmap渲染来更新AVI Player 271

12.3.4 运行使用Bitmap渲染的AVI Player 278

12.4 使用OpenGL ES渲染 279

12.4.1 使用OpenGL ES API 279

12.4.2 启用OpenGL ES 1.x API 279

12.4.3 启用OpenGL ES 2.0 API 280

12.4.4 用OpenGL ES渲染来更新AVI Player 280

12.5 使用原生Window API进行渲染 290

12.5.1 启用原生Window API 290

12.5.2 使用原生Window API 291

12.5.3 用原生window渲染器来更新AVI Player 293

12.5.4 EGL图形库 301

12.6 小结 301

第13章 原生音频API 303

13.1 使用OpenSL ES API 303

13.1.1 与OpenSL ES标准的兼容性 304

13.1.2 音频许可 304

13.2 创建WAVE音频播放器 304

13.2.1 将WAVELib作为NDK导入模块 304

13.2.2 创建WAVE播放器Android应用程序 306

13.2.3 创建WAVE播放器主Activity 306

13.2.4 实现WAVE Aduio播放 310

13.3 运行WAVE Audio Player 327

13.4 小结 328

第14章 程序概要分析和NEON优化 329

14.1 用GNU Profiler度量性能 329

14.1.1 安装Android NDK Profiler 329

14.1.2 启用Android NDK Profiler 330

14.1.3 使用GNU Profiler分析gmon.out文件 331

14.2 使用ARM NEON Intrinsics进行优化 332

14.2.1 ARM NEON技术概述 333

14.2.2 给AVI Player添加一个亮度过滤器 333

14.2.3 为AVI播放器启用Android NDK Profiler 336

14.2.4 AVI Player程序概要分析 337

14.2.5 使用NEON Intrinsics优化Brightness Filter 338

14.3 自动向量化 342

14.3.1 启用自动向量化 343

14.3.2 自动向量化问题的发现和排除 344

14.4 小结 344

嵌入式Linux应用程序开发标准教程(第2版全)

10-11

接着系统地讲解了嵌入式Linux的环境搭建,以及嵌入式Linux的I/O与文件系统的开发、进程控制开发、进程间通信开发、网络应用开发、基于中断的开发、设备驱动程序的开发以及嵌入式图形界面的开发等,并且还安排了丰富...

C语言UDP socket编程

热门推荐

jiang_2018的博客

04-06

1万+

C语言UDP socket编程

UDP 服务器步骤如下:

- 1.创建等链接套接字fd=socket()

- 2.绑定待链接套接字bind(fd,服务器ip和端口)

- 3.等待信息recvfrom(fd,对端地址)

UDP 客户端步骤如下:

- 1.创建待连接套接字fd=scoket()

- 2.发送信息sendto(fd,服务器ip和端口)

UDP服务器

int main(i...

GOlang语言实现TCP调试助手客户端功能并把返回的数据结果保存到结构体数组里面(解析Modbus TCP协议为案例)

weixin_41920684的博客

08-24

640

package main

import (

"fmt"

"net"

"strings"

)

const (

BitNotConsidered ="不考虑的比特位"

bit01 = "断纤告警"

bit02 = "高温告警"

bit03 = "温升告警"

)

type TotalStat struct {

GlobalAlarm string

//第一个寄存器bit0~bit3的状态

FirstBitGlobalAlarmStatus stri.

【socket编程】TCP服务器、UDP服务器、本地套接字【C语言代码实现】

crr411422的博客

07-13

1208

大小端概念、网络字节序和主机字节序、网络套接字函数(socket connect bind accept listen等)、TCP服务器(进程版和线程版)、UDP服务器、本地套接字。这些都是 C语言实现的代码,建议理解并自行敲出来。

UDP通信----代码及结果演示(C语言)

qq_70067877的博客

09-29

166

UDP通信的服务器、客户端代码及演示结果

UDP通信 (C语言实现)

动感超人_Crush

03-22

3101

直接看代码吧 v๑乛◡乛๑

网络编程——UDP编程

JiaYu的博客

05-16

1712

在代码中包含必要的头文件,以便使用UDP编程所需的函数和数据类型。使用 socket() 函数创建一个套接字,该套接字将用于网络通信。套接字是一个整数值,它表示一个打开的文件描述符,用于在网络上发送和接收数据。使用 bind() 函数将套接字绑定到指定的地址和端口上。(1)创建数据报套接字(socket(,SOCK_DGRAM,))在通信结束后,使用 close() 函数关闭套接字,释放资源。(1)创建数据报套接字(socket())(4)关闭套接字(close())(4)关闭套接字(close())

pandasai-1.5.19.tar.gz

最新发布

03-09

Python库是一组预先编写的代码模块,旨在帮助开发者实现特定的编程任务,无需从零开始编写代码。这些库可以包括各种功能,如数学运算、文件操作、数据分析和网络编程等。Python社区提供了大量的第三方库,如NumPy、Pandas和Requests,极大地丰富了Python的应用领域,从数据科学到Web开发。Python库的丰富性是Python成为最受欢迎的编程语言之一的关键原因之一。这些库不仅为初学者提供了快速入门的途径,而且为经验丰富的开发者提供了强大的工具,以高效率、高质量地完成复杂任务。例如,Matplotlib和Seaborn库在数据可视化领域内非常受欢迎,它们提供了广泛的工具和技术,可以创建高度定制化的图表和图形,帮助数据科学家和分析师在数据探索和结果展示中更有效地传达信息。

基于linux的网络聊天室C语言mysql

05-17

要实现一个基于Linux的网络聊天室,你需要使用C语言编程语言和MySQL数据库。以下是一些基本步骤:

1. 选择适当的网络通信协议,如TCP/IP或UDP。你需要理解套接字编程,可以使用socket函数库。

2. 实现服务端和客户端程序。服务端程序应该能够接收客户端的连接请求,并将消息广播给所有连接的客户端。客户端程序应该能够连接到服务器,并能够发送和接收消息。

3. 为了存储聊天记录和用户信息,你需要使用MySQL数据库。你需要使用C语言编写MySQL客户端程序,以便服务端程序可以与数据库进行交互。

4. 在数据库中创建表来存储聊天记录和用户信息。你需要设计表结构和关系。

5. 实现用户注册和登录功能。在数据库中存储用户信息,包括用户名和密码。当用户登录时,服务端程序应该验证用户的凭据,并允许用户访问聊天室。

6. 实现聊天室管理功能。只有管理员才能删除或禁止用户访问聊天室。

7. 实现私人聊天功能。允许用户私下发送消息给其他用户。

以上是实现基于Linux的网络聊天室的一些基本步骤。你需要深入了解每个步骤,并进行适当的调试和测试,以确保程序正常运行。

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

非常没帮助

没帮助

一般

有帮助

非常有帮助

提交

诗筱涵

CSDN认证博客专家

CSDN认证企业博客

码龄10年

暂无认证

1903

原创

1749

周排名

147

总排名

435万+

访问

等级

4万+

积分

4173

粉丝

4644

获赞

1190

评论

2万+

收藏

私信

关注

热门文章

ubuntu如何查看磁盘空间

77928

如何使用串口调试助手(调试串口)

63815

手把手教你在VSCode中使用Git

38116

APM(pixhawk)飞控疑难杂症解决方法汇总

38041

来解决一下putty 树莓派 remote side unexpectedly closed network connection

34722

分类专栏

无人机-SLAM-D435i

77篇

MVS

2篇

用简单代码实现功能

12篇

无人机-SLAM-vins

77篇

无人机-SLAM-T265

146篇

多传感器融合/状态估计

52篇

点线SLAM

8篇

NVIDIA jetson板卡

55篇

OpenCV

114篇

ROS

284篇

rtsp

4篇

github

62篇

无人机-f-个人笔记

79篇

无人机-阿木-普罗米修斯-源码分析

45篇

无人机-pixhawk-PX4

148篇

无人机-mavros控制Pixhawk offboard

113篇

无人机-pixhawk

170篇

无人机-SLAM

181篇

深度学习SLAM

5篇

ROS-消息

10篇

无人机-SLAM-激光雷达

12篇

ROS2

4篇

无人机-mavlink

32篇

STM32-串口通信协议

116篇

多线程编程(Linux应用层编程)

18篇

网络编程(Linux应用层编程)

91篇

C++

160篇

linux服务器编程(linux应用层编程主要方向)

26篇

docker

46篇

XTDrone

17篇

无人机-a-个人笔记

251篇

C语言

80篇

无人机-元件-机架

14篇

无人机

416篇

无人机-苍穹四轴

24篇

VIO-GPS

23篇

无人机-SLAM-vins-GPS

30篇

无人机-SLAM-APM树莓派T265

50篇

无人机-SLAM-仿真(总)

69篇

无人机-阿木-普罗米修斯

31篇

无人机-阿木实验室

30篇

卡尔曼滤波

34篇

无人机-智能无人机课程

27篇

无人机-自己实现VIO

41篇

无人机-pixhawk-APM

10篇

ROS-CMakeLists

38篇

驱动

25篇

FreeRTOS

83篇

STM32

152篇

其他

15篇

无人机-SLAM-理论

46篇

最优化理论

17篇

控制理论-PID

33篇

C++-STL

24篇

QT

12篇

无人机-自制飞控(硬件到软件)

11篇

PCB-STM32最小系统

20篇

PCB

71篇

无人机-ACfly

56篇

Linux应用层编程

48篇

数据结构

23篇

leetcode

9篇

无人机-无名

14篇

华清

10篇

嵌入式

23篇

无人机-路径规划(包含fastplanner)

10篇

驱动-STM32

10篇

进程编程(Linux应用层编程)

15篇

无人机-TBUS

12篇

无人机-SLAM-GAAS

19篇

python

25篇

平衡车

25篇

无人机-SLAM-仿真

14篇

机器学习

10篇

无人机-ACfly-T265

41篇

无人机-理论

13篇

控制理论

40篇

无人机-正点原子minifly

6篇

无人机-一些飞控基本上手操作

4篇

控制理论-欠驱动系统

10篇

IO编程(linux应用层编程)

5篇

OZO

18篇

tensorflow

14篇

深度学习

15篇

最新评论

PID在线调参这个方法不错!!!!!这可以让PID调参方便很多啊!!!!!!!而且可以很方便看到各个参数变化造成的影响!!!!!!!

塔塔怎么了:

现在的taobao上的轮趣

PID在线调参这个方法不错!!!!!这可以让PID调参方便很多啊!!!!!!!而且可以很方便看到各个参数变化造成的影响!!!!!!!

塔塔怎么了:

现在的taobao上的轮趣

北东地/东北天两种导航坐标系与姿态转换

w779261026:

x指东,它的转动角就是俯仰,前进方向是y轴,y转动才是横滚

北东地/东北天两种导航坐标系与姿态转换

w779261026:

x指东,它的转动角就是俯仰,前进方向是y轴,y转动才是横滚

北东地/东北天两种导航坐标系与姿态转换

w779261026:

你是对的,x指东,为横滚

您愿意向朋友推荐“博客详情页”吗?

强烈不推荐

不推荐

一般般

推荐

强烈推荐

提交

最新文章

16位深度图显示和存储时要转为8位的灰度图的原因

用rs-enumerate-devices -c命令可以查看D435i所有可以支持的分辨率,帧率,所有的相机内参外参

SLAM精度评估指标ATE RMSE和RPE RMSE及evo结果分析

2024

03月

21篇

02月

49篇

2022年3篇

2021年1033篇

2020年1562篇

2019年16篇

2017年2篇

目录

目录

分类专栏

无人机-SLAM-D435i

77篇

MVS

2篇

用简单代码实现功能

12篇

无人机-SLAM-vins

77篇

无人机-SLAM-T265

146篇

多传感器融合/状态估计

52篇

点线SLAM

8篇

NVIDIA jetson板卡

55篇

OpenCV

114篇

ROS

284篇

rtsp

4篇

github

62篇

无人机-f-个人笔记

79篇

无人机-阿木-普罗米修斯-源码分析

45篇

无人机-pixhawk-PX4

148篇

无人机-mavros控制Pixhawk offboard

113篇

无人机-pixhawk

170篇

无人机-SLAM

181篇

深度学习SLAM

5篇

ROS-消息

10篇

无人机-SLAM-激光雷达

12篇

ROS2

4篇

无人机-mavlink

32篇

STM32-串口通信协议

116篇

多线程编程(Linux应用层编程)

18篇

网络编程(Linux应用层编程)

91篇

C++

160篇

linux服务器编程(linux应用层编程主要方向)

26篇

docker

46篇

XTDrone

17篇

无人机-a-个人笔记

251篇

C语言

80篇

无人机-元件-机架

14篇

无人机

416篇

无人机-苍穹四轴

24篇

VIO-GPS

23篇

无人机-SLAM-vins-GPS

30篇

无人机-SLAM-APM树莓派T265

50篇

无人机-SLAM-仿真(总)

69篇

无人机-阿木-普罗米修斯

31篇

无人机-阿木实验室

30篇

卡尔曼滤波

34篇

无人机-智能无人机课程

27篇

无人机-自己实现VIO

41篇

无人机-pixhawk-APM

10篇

ROS-CMakeLists

38篇

驱动

25篇

FreeRTOS

83篇

STM32

152篇

其他

15篇

无人机-SLAM-理论

46篇

最优化理论

17篇

控制理论-PID

33篇

C++-STL

24篇

QT

12篇

无人机-自制飞控(硬件到软件)

11篇

PCB-STM32最小系统

20篇

PCB

71篇

无人机-ACfly

56篇

Linux应用层编程

48篇

数据结构

23篇

leetcode

9篇

无人机-无名

14篇

华清

10篇

嵌入式

23篇

无人机-路径规划(包含fastplanner)

10篇

驱动-STM32

10篇

进程编程(Linux应用层编程)

15篇

无人机-TBUS

12篇

无人机-SLAM-GAAS

19篇

python

25篇

平衡车

25篇

无人机-SLAM-仿真

14篇

机器学习

10篇

无人机-ACfly-T265

41篇

无人机-理论

13篇

控制理论

40篇

无人机-正点原子minifly

6篇

无人机-一些飞控基本上手操作

4篇

控制理论-欠驱动系统

10篇

IO编程(linux应用层编程)

5篇

OZO

18篇

tensorflow

14篇

深度学习

15篇

目录

评论

被折叠的  条评论

为什么被折叠?

到【灌水乐园】发言

查看更多评论

添加红包

祝福语

请填写红包祝福语或标题

红包数量

红包个数最小为10个

红包总金额

红包金额最低5元

余额支付

当前余额3.43元

前往充值 >

需支付:10.00元

取消

确定

下一步

知道了

成就一亿技术人!

领取后你会自动成为博主和红包主的粉丝

规则

hope_wisdom 发出的红包

实付元

使用余额支付

点击重新获取

扫码支付

钱包余额

0

抵扣说明:

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

余额充值

耗时一周给大家整理的计算机网络编程基础(超级详细~) - 知乎

耗时一周给大家整理的计算机网络编程基础(超级详细~) - 知乎首发于网络协议栈专题切换模式写文章登录/注册耗时一周给大家整理的计算机网络编程基础(超级详细~)玩转Linux内核官方社区最新信息搜集、文章推送、教程学习、技巧分享等~计算机网络模型;TCP/IP 与 OSI 都是为了使网络中的两台计算机能够互相连接并实现通信与回应,但他们最大的不同在于,OSI 是一个理论上的网络通信模型,而 TCP/IP 则是实际上的网络通信标准。一、OSI七层模型1、物理层:实现计算机节点之间比特流的透明传输,规定传输媒体接口的标准,屏蔽掉具体传输介质和物理设备的差异,使数据链路层不必关心网络的具体传输介质,按照物理层规定的标准传输数据就行2、数据链路层:通过差错控制、流量控制等方法,使有差错的物理线路变为无差错的数据链路。数据链路层的几个基本方法:数据封装成桢、透明传输、差错控制、流量控制:封装成桢:把网络层数据报加头和尾,封装成帧,帧头中包括源MAC地址和目的MAC地址。透明传输:零比特填充、转义字符。差错控制:接收者检测错误,如果发现差错,丢弃该帧,差错控制方法有 CRC 循环冗余码流量控制:控制发送的传输速度,使得接收方来得及接收。传输层TCP也有流量控制功能,但TCP是端到端的流量控制,链路层是点到点(比如一个路由器到下一个路由器)3、网络层:实现网络地址与物理地址的转换,并通过路由选择算法为分组通过通信子网选择最适当的路径网络层最重要的一个功能就是:路由选择。路由一般包括路由表和路由算法两个方面。每个路由器都必须建立和维护自身的路由表,一种是静态维护,也就是人工设置,适用于小型网络;另一种就是动态维护,是在运行过程中根据网络情况自动地动态维护路由表。4、传输层:提供源端与目的端之间提供可靠的透明数据传输,传输层协议为不同主机上运行的进程提供逻辑通信。网络层协议负责的是提供主机间的逻辑通信;传输层协议负责的是提供进程间的逻辑通信。5、会话层:是用户应用程序和网络之间的接口,负责在网络中的两节点之间建立、维持、终止通信。6、表示层:处理用户数据的表示问题,如数据的编码、格式转换、加密和解密、压缩和解压缩。7、应用层:为用户的应用进程提供网络通信服务,完成和实现用户请求的各种服务。【文章福利】小编推荐自己的Linux内核技术交流群:【865977150】整理了一些个人觉得比较好的学习书籍、视频资料共享在群文件里面,有需要的可以自行添加哦!!!前100名进群领取,额外赠送一份价值699的内核资料包(含视频教程、电子书、实战项目及代码)学习直通车:内核资料直通车:二、TCP/IP模型TCP/IP协议模型(Transmission Control Protocol/Internet Protocol),包含了一系列构成互联网基础的网络协议,是Internet的核心协议。TCP/IP协议族按照层次由上到下,层层包装。上图表示了TCP/IP协议中每个层的作用,而TCP/IP协议通信的过程其实就对应着数据入栈与出栈的过程。入栈的过程,数据发送方每层不断地封装首部与尾部,添加一些传输的信息,确保能传输到目的地。出栈的过程,数据接收方每层不断地拆除首部与尾部,得到最终传输的数据。三,网络层实现网络地址与物理地址的转换,并通过路由选择算法为分组通过通信子网选择最适当的路径1、IP地址与物理地址:物理地址是数据链路层和物理层使用的地址,IP地址是网络层和以上各层使用的地址,是一种逻辑地址,其中ARP协议将IP地址转换成物理地址。2、ARP地址解析协议的工作原理:ARP 是根据 IP 地址获取 MAC 地址的一种协议,核心原理就是广播发送ARP请求,单播发送ARP响应(1)每个主机都在自己的ARP缓冲区中建立一个ARP列表,以表示 IP 地址和 MAC 地址之间的对应关系。(2)当源主机要发送数据时,先检查ARP列表中是否有该 IP 地址对应的 MAC 地址,如果有,则直接发送数据;如果没有,就向本网段的所有主机发送ARP数据包,用于查询目的主机的MAC地址,该数据包包括的内容有:源主机IP地址,源主机MAC地址,目的主机的IP。(3)当本网络的所有主机收到该ARP数据包时,首先检查数据包中的IP地址是否是自己的IP地址,如果不是,则忽略该数据包,如果是,则首先从数据包中取出源主机的IP和MAC地址写入到ARP列表中,如果已经存在,则覆盖,然后将自己的MAC地址写入ARP响应包中,告诉源主机自己是它想要找的MAC地址。(4)源主机收到 ARP 响应包后,将目的主机的 IP 和 MAC 地址写入ARP列表,并利用此信息发送数据。如果源主机一直没有收到ARP响应数据包,表示ARP查询失败3、RARP逆地址解析协议:RARP是逆地址解析协议,作用是完成硬件地址到IP地址的映射,主要用于无盘工作站,因为给无盘工作站配置的IP地址不能保存。工作流程:在网络中配置一台RARP服务器,里面保存着 MAC 地址和 IP 地址的映射关系,当无盘工作站启动后,就封装一个RARP数据包,里面有其MAC地址,然后广播到网络上去,当服务器收到请求包后,就查找对应的MAC地址的IP地址装入响应报文中发回给请求者。因为需要广播请求报文,因此RARP只能用于具有广播能力的网络。4、DHCP协议:动态主机配置协议,对 IP地址进行集中管理和分配,提升地址的使用率,通过DHCP协议,可以使客户机自动获得服务器分配的lP地址和子网掩码5、ICMP协议:因特网控制报文协议,用于在IP主机、路由器之间传递控制消息(控制消息是指网络通不通、主机是否可达、路由器是否可用等网络本身的消息),确认 IP 包是否成功到达目标地址。因为 IP 协议并不是一个可靠的协议,它不保证数据被送达,当传送IP数据包发生错误,比如主机不可达、路由不可达等等,ICMP协议将会把错误信息封包,然后传送回给主机,给主机一个处理错误的机会。ICMP报文有两种:差错报告报文和询问报文。以下是4种常见的ICMP差错报告报文6、交换机与路由器的区别:(1)工作所处的OSI层次不一样,交换机工作在OSI第二层数据链路层,路由器工作在OSI第三层网络层;(2)寻址方式不同:交换机根据MAC地址寻址,路由器根据IP地址寻址;(3)转发速不同:交换机的转发速度快,路由器转发速度相对较慢。7、路由选择协议:(1)内部网关协议IGP:① RIP(Routing Information Protocol):是一种动态路由选择协议,基于距离矢量算法,使用“跳数”来衡量到达目标地址的路由距离,并且只与自己相邻的路由器交换信息,范围限制在15跳之内。② OSPF:开放最短路径优先协议,使用Dijskra算法计算出到达每一网络的最短路径,并在检测到 链路的情况发生变化时(如链路失效),就执行该算法快速收敛到新的无环路拓扑。(2)外部网关协议:BGP:边界网关协议,BGP 是力求寻找一条能够到达目的网络 且 较好的路由,而并非要寻找一条最佳路由。BGP采用路径向量路由选择协议。四,传输层传输层主要提供不同主机上进程间 逻辑通信 + 可靠传输 或者 不可靠传输的功能。一、TCP 和 UDP:1、TCP 和 UDP的区别?(1)TCP是面向字节流的,基本传输单位是TCP报文段;UDP是面向报文的,基本传输单位是是用户数据报;面向字节流:应用程序和TCP的交互是一次一个数据块(大小不等),但TCP把应用程序看成是一连串的无结构的字节流。TCP有一个缓冲,当应用程序传送的数据块太长,TCP就可以把它划分短一些再传送。面向报文:面向报文的传输方式是应用层交给UDP多长的报文,UDP就照样发送。因此,应用程序必须选择合适大小的报文。(2)TCP 注重安全可靠性,连接双方在进行通信前,需进行三次握手建立连接。UDP 是无连接的,使用最大努力交付,即不保证可靠交付。(3)UDP 不需要连接等待,所以数据传输快,而 TCP 传输效率相对较低(4)TCP首部开销是20个字节;UDP的首部开销是8个字节,这也是减少网络传输开销的一方面(5)TCP有拥塞控制和流量控制,而UDP没有拥塞控制和流量控制(6)TCP支持点对点通信,提供全双工通信,不提供广播或多播服务;UDP支持一对一、一对多、多对一、多对多的通信模式。2、TCP 和 UDP 的适用场景:(1)当对网络通讯质量要求不高时,并且要求网络通讯速度能尽量的快,这时就可以使用UDP。比如即使通信: 语音、 视频 、直播等(2)当对网络通讯质量有要求时,要求整个数据准确无误可靠的传递给对方,这时就适用使用 TCP 协议,一般用于文件传输、发送和接收邮件等场景。比如HTTP、HTTPS、FTP等传输文件的协议,POP、SMTP等邮件传输的协议都是使用 TCP 协议① TCP对应的协议:FTP:文件传输协议,使用21端口Telnet:远程终端接入,使用23端口,用户可以以自己的身份远程连接到计算机上,可提供基于DOS模式下的通信服务。SMTP:邮件传送协议,用于发送邮件,使用25端口POP3:邮件传送协议,P用于接收邮件。使用110端口HTTP:万维网超文本传输协议,是从Web服务器传输超文本到本地浏览器的传送协议② UDP对应的协议:DNS:域名解析服务,将域名地址转换为IP地址,使用53号端口;SNMP:网络管理协议,用来管理网络设备,使用161号端口;TFTP:简单文件传输协议,提供不复杂、开销不大的文件传输服务,使用 69 端口;NFS:远程文件服务器RIP:路由信息协议DHCP:动态主机配置协议IGMP:网际组管理协议3、TCP的首部字段:(1)源端口和目的端口:分别占16位,指发送方应用程序的端口和目的方应用程序的端口号,通过 IP 地址 + 端口号就可以确定一个进程地址(2)序号(Sequense Number,SN):在一个TCP连接中传送的字节流中的每一个字节都按顺序编号,该字段表示本报文段所发送数据的第一个字节的序号。(初始序号称为 Init Sequense Number, ISN)例如,一报文段的序号是 101,共有 100 字节的数据。这就表明:本报文段的数据的第一个字节的序号是 101,最后一个字节的序号是 200。显然,下一个报文段的数据序号应当从 201 开始,即下一个报文段的序号字段值应为 201。(3)确认号 ack:期望收到对方下一个报文段的第一个数据字节的序号。若确认号为 N,则表明:到序号 N-1 为止的所有数据都已正确收到。(4)头部长度:指出 TCP报文段的数据起始处 距离 TCP报文段的起始处有多远。这个字段实际上是指出TCP报文段的首部长度。(5)保留位:占6位,应置为 0,保留为今后使用。(6)6个控制位:用于说明该报文段的性质:① 紧急位URG:当 URG = 1 时,表明此报文段中有紧急数据,是高优先级的数据,应尽快发送,不用在缓存中排队。② 确认ACK:仅当 ACK = 1 时确认号字段才有效,当 ACK = 0 时确认号无效。TCP 规定,在连接建立后所有传送的报文段都必须把 ACK 置为 1。③ 推送PSH:接收方收到 PSH = 1 的报文段时,就直接发送给应用进程,而不用等到整个缓冲区都填满了后再向上传送。④ 复位RST:当 RST = 1 时,表明 TCP 连接中出现了严重错误(如由于主机崩溃或其他原因),必须释放连接,然后再重新建立传输连接。⑤ 同步SYN:SYN = 1 表示这是一个连接请求或连接接受报文。当 SYN = 1 而 ACK = 0 时,表明这是一个连接请求报文段。对方若同意建立连接,则应在响应的报文段中使 SYN = 1 且 ACK = 1。⑥ 终止FIN:用来释放一个连接。当 FIN = 1时,表明此报文段的发送发的数据已发送完毕,并要求释放运输连接。(7)窗口大小:16位,用于控制发送端的滑动窗口大小(8)校检和:16位,校验数据段是否未被修改(9)紧急指针:16位。二、TCP连接的建立与断开:1、建立连接的三次握手:(1)第一次握手:客户端向服务端发送一个 SYN 报文(SYN = 1),并指明客户端初始化序列号 ISN,即seq = x,表示本报文所发送的第一个字节的序号。此时客户端处于 SYN_Sent 状态,等待服务端确认。三次握手的一个重要功能是客户端和服务端交换 ISN,以便让对方知道接下来接收数据时如何按序列号组装数据。ISN 是动态生成的,并非固定,因此每个连接都将具有不同的 ISN。如果 ISN 是固定的,攻击者很容易猜出后续的确认号。(2)第二次握手:服务端收到数据包后,由 SYN = 1 知道客户端请求建立连接,那么就会对这个TCP 连接分配缓存和变量(缓存指的是一个字节流队列),接着返回一个确认报文:设置 SYN = 1,ACK = 1,同时指定自己的初始化序列号 ISN,即图中的 seq = y,并把客户端的 ISN + 1 作为确认号 ack 的值,表示已经收到了客户端发来的的 SYN 报文,希望收到的下一个数据的第一个字节的序号是 x + 1,此时服务端进入SYN_REVD状态。(3)第三次握手:客户端收到确认后,检查ACK是否为1,ack是否为 x +1,如果正确,则给服务端发送一个 ACK 报文:设置 ACK = 1,把服务端的 ISN + 1 作为 ack 的值,表示已经收到了服务端发来的 SYN 报文,希望收到的下一个数据的第一个字节的序号是 y + 1,并指明此时客户端的序列号 seq = x + 1,此时客户端和服务器端都进入 ESTABLISHED 状态。完成三次握手,随后Client与Server之间可以开始传输数据了。此时 SYN 控制位变为 0,表示这不是建立连接的请求了,要正式发数据了。2、为什么不能用两次握手进行建立连接?(1)三次握手目的是确认双方的接收与发送能力是否正常,同步连接双方的初始化序列号 ISN,为后面的可靠性传输做准备。而两次握手只有服务端对客户端的起始序列号做了确认,但客户端却没有对服务端的初始序列号做确认,不能保证传输的可靠性。(2)三次握手可以防止已失效的连接请求报文段突然又传送到了服务端,导致服务器错误地建立连接,浪费服务端的连接资源。客户端发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达Server。本来这是一个早已失效的报文段,但Server收到此失效的连接请求报文段后:① 假设不采用“三次握手”,那么只要Sever发出确认,新的连接就建立了。但由于现在Client并没有发出建立连接的请求,因此不会理睬Server的确认,也不会向Server发送数据。而Server却以为新的连接已经建立,并一直等待Client发来数据,这样,Server的很多资源就白白浪费掉了② 而采用“三次握手”协议,只要Server收不到来自Client的确认,就知道Client并没有要求建立请求,就不会建立连接了。3、断开连接的四次挥手:(1)第一次挥手:客户端发送一个 FIN 报文,设置 FIN = 1 并指定序列号 seq = u(u 是之前传送过来的最后一个字节的序号 + 1),主动关闭 TCP 连接,此时客户端进入FIN_WAIT_1状态;(2)第二次挥手:服务端收到 FIN 报文后,由FIN=1 知道客户端请求关闭连接,则返回确认报文:设置ACK = 1,ack = u + 1,seq = v(v 的值取决于服务器发送给客户端之前的一个包确认号是多少)服务端进入CLOSE_WAIT状态,此时TCP连接处于半关闭状态,即客户端不能向服务端发送报文,只能接收,但服务端仍然可以向客户端发送数据。客户端收到服务端的确认后,进入 FIN_WAIT2 状态,等待服务端发出的连接释放报文段。(3)第三次挥手:当服务端没有要向客户端发送的数据时,就向客户端发送一个 FIN 报文,设置 FIN = 1 并指定序列号 seq = w(w 的值取决于服务器发送给客户端之前的一个包确认号是多少),用于关闭服务端到客户端的数据传送。此时服务器处于 LAST_ACK 状态(4)第四次挥手:客户端收到 FIN 报文后,发送给服务端一个 ACK 报文作为应答:设置 ACK=1 和 ack = w +1。发送之后,客户端处于 TIME_WAIT状态,如果服务端接收到这个数据包,则进入CLOSED状态,完成四次挥手。4、为什么需要 TIME_WAIT 状态:TIME_WAIT 状态持续 2MSL(最大报文存活时间),约4分钟才转换成CLOSE状态。由于TIME_WAIT 的时间会非常长,因此服务端应尽量减少主动关闭连接,TIME_WAIT 的主要作用有:(1)重发丢失的 ACK 报文,保证连接可靠的关闭:由于网络等原因,无法保证最后一次挥手的 ACK 报文一定能传送给对方,如果 ACK 丢失,对方会超时重传 FIN,主动关闭端会再次响应ACK过去;如果没有 TIME_WAIT 状态,直接关闭,对方重传的FIN报文则被响应一个RST报文,此RST会被动关闭端被解析成错误。同时,服务器就因为接收不到客户端的信息而无法正常关闭。(2)保证本次连接的重复数据段从网络中消失:如果存在两个连接,第一个连接正常关闭,第二个相同的连接紧接着建立;如果第一个连接的某些数据仍然滞留在网络中,这些延迟数据在建立新连接之后才到达,则会干扰第二连接,等待 2MSL 可以让上次连接的报文数据消逝在网络中。5、为什么需要四次挥手:TCP 是全双工模式,并且支持半关闭特性,提供了连接的一端在结束发送后还能接收来自另一端数据的能力。任何一方都可以在数据传送结束后发出连接释放的通知,待对方确认后进入半关闭状态。当另一方也没有数据再发送的时候,则发出连接释放通知,对方确认后就完全关闭了 TCP 连接。通俗的来说,两次握手就可以释放一端到另一端的 TCP 连接,完全释放连接一共需要四次握手。6、什么是SYN洪泛:SYN 洪泛是指利用 TCP 需要三次握手的特性,攻击者伪造 SYN 报文向服务器发起连接,服务器在收到报文后用 ACK 应答,但之后攻击者不再对该响应进行应答,造成一个半连接。假设攻击者发送大量这样的报文,那么被攻击主机就会造成大量的半连接,耗尽其资源,导致正常的 SYN 请求因为队列满而被丢弃,使得正常用户无法访问。半连接队列:服务器第一次收到客户端的 SYN 之后,就会处于 SYN_RCVD 状态,此时双方还没有完全建立其连接,服务器会把这种状态下的请求连接放在一个队列里,我们把这种队列称之为半连接队列。当然还有一个全连接队列,完成三次握手后建立起的连接就会放在全连接队列中。7、三次握手过程中是否可以携带数据:第三次握手时是可以携带数据的,但第一二次握手时不可以携带数据。(1)假如第一次握手可以携带数据的话,那么会放大 SYN 洪泛。如果有人要恶意攻击服务器,每次都在第一次握手中的 SYN 报文中放入大量的数据,然后疯狂重复发送 SYN 报文的话,就会让服务器开辟大量的缓存来接收这些报文,内存会很容易耗尽,从而拒绝服务。(2) 第三次握手时客户端已经处于 ESTABLISHED 状态,对于客户端来说,他已经建立起连接了,并且已经知道服务器的接收和发送能力是正常的,所以也就可以携带数据了。8、TCP的粘包和拆包:程序需要发送的数据大小和TCP报文段能发送MSS(Maximum Segment Size,最大报文长度)是不一样的。大于MSS时,就需要把程序数据拆分为多个TCP报文段,称之为拆包;小于时,则要考虑合并多个程序数据为一个TCP报文段,则是粘包;其中MSS = TCP报文段长度-TCP首部长度。在IP协议层或者链路层、物理层,都存在拆包、粘包现象。解决粘包和拆包的方法主要有:(1)在数据尾部增加特殊字符进行分割;(2)将数据定为固定大小;(3)将数据分为两部分,一部分是头部,一部分是内容体;其中头部结构大小固定,且有一个字段声明内容体的大小三、TCP可靠性传输:1、TCP 如何保证可靠性传输:(1)三次握手(2)应答机制与超时重传:TCP接收端收到发送端的数据时,它将发送一个确认。当TCP发送端发出一个报文段后,它会启动一个定时器,等待接收端的确认报文段,如果不能及时收到一个确认,将重发这个报文段。(3)数据包校验与丢弃重复数据:TCP会检测数据在传输过程中的任何变化,若校验出包有错,则丢弃报文段并且不给出响应,这时TCP会超时重发数据;对于重复数据,则进行丢弃;(4)对失序数据包进行重排序:既然TCP报文段作为IP数据报来传输,而IP数据报的到达可能会失序,因此TCP报文段的到达也可能会失序。TCP将对失序数据进行重新排序,然后才交给应用层;(5)流量控制:TCP 连接的每一方都有固定大小的缓冲空间。TCP 的接收端只允许另一端发送接收端缓冲区所能接纳的数据,防止较快主机致使较慢主机的缓冲区溢出。TCP使用的流量控制协议是可变大小的滑动窗口协议。(6)拥塞控制:网络拥塞时,减少数据的发送。2、TCP的流量控制:所谓流量控制就是让发送方的发送速率不要太快,让接收方来得及接收。因为如果发送方把数据发送得过快,接收方可能会来不及接收,这就会造成数据的丢失。TCP的流量控制是通过大小可变的滑动窗口来实现的。接收端将自己可以接收的缓冲区大小放入TCP首部中的“窗口大小”字段,通过ACK报文来通知发送端,滑动窗口是接收端用来控制发送端发送数据的大小,从而达到流量控制其实发送方的窗口上限,是取值拥塞窗口和滑动窗口两者的最小值。当滑动窗口为 0 时,发送方一般不能再发送数据包,但有两种情况除外,一种情况是可以发送紧急数据,例如,允许用户终止在远端机上的运行进程。另一种情况是发送方可以发送一个 1 字节的数据报来通知接收方重新声明它希望接收的下一字节及发送方的滑动窗口大小。设A向B发送数据。在连接建立时,B告诉了A:“我的接收窗口是 rwnd = 400 ”(这里的 rwnd 表示 receiver window) 。因此,发送方的发送窗口不能超过接收方给出的接收窗口的数值。假设每一个报文段为100字节长,而数据报文段序号的初始值设为1。从图中可以看出,B进行了三次流量控制。第一次把窗口减少到 rwnd = 300 ,第二次又减到了 rwnd = 100 ,最后减到 rwnd = 0 ,即不允许发送方再发送数据了。这种使发送方暂停发送的状态将持续到主机B重新发出一个新的窗口值为止。B向A发送的三个报文段都设置了 ACK = 1 ,只有在 ACK=1 时确认号字段才有意义。3、TCP的拥塞控制:拥塞控制就是防止过多的数据注入网络中,使网络中的路由器或链路不致过载。发送方维持一个拥塞窗口cwnd 的状态变量。拥塞窗口的大小动态变化,取决于网络的拥塞程度,发送方让自己的发送窗口等于拥塞窗口。只要网络没有出现拥塞,拥塞窗口就再增大一些,以便把更多的分组发送出去。但只要网络出现拥塞,拥塞窗口就减小一些,以减少注入到网络中的分组数。 拥塞控制的方法主要有以下几种:慢启动、拥塞避免、快重传和快恢复。(1)慢开始算法:当发送主机开始发送数据时,不要一开始就发送大量的数据,因为不清楚网络的拥塞情况,而是试探一下网络的拥塞情况,由小到大逐渐增大发送窗口。在开始发送报文段时先设置cwnd=1,使得发送方在开始时只发送一个报文段,然后每经过一个传输轮次RTT,拥塞窗口 cwnd 就加倍。另外,为了防止拥塞窗口cwnd增长过大引起网络拥塞,还需要设置一个慢开始门限 ssthresh 状态变量。当 cwnd < ssthresh 时,使用上述的慢开始算法。当 cwnd = ssthresh 时,既可使用慢开始算法,也可使用拥塞控制避免算法。当 cwnd > ssthresh 时,停止使用慢开始算法而改用拥塞避免算法。(2)拥塞避免算法:让拥塞窗口cwnd缓慢地增大,即每经过一个往返时间RTT就把发送方的拥塞窗口cwnd加1。这样拥塞窗口cwnd按线性规律缓慢增长,比慢开始算法的拥塞窗口增长速率缓慢得多。无论在慢开始阶段还是在拥塞避免阶段,只要网络出现拥塞(其根据就是没有收到确认),就要把慢开始门限ssthresh设置为出现拥塞时的拥塞窗口值的一半(但不能小于2)。然后把拥塞窗口cwnd 设置为1,执行慢开始算法。这样做的目的就是要迅速减少主机发送到网络中的数据量,使得发生拥塞的路由器有足够时间把队列中积压的数据处理完毕。过程图如下:(3)快重传:快重传要求接收方在收到一个失序的报文段后就立即发出重复确认(使发送方及早知道有报文段没有到达对方)而不必等到自己发送数据时捎带确认。发送方只要一连收到三个重复确认就应当立即重传对方尚未收到的报文段,而不必继续等待设置的重传计时器时间到期。接收方收到了M1和M2后都分别发出了确认。现在假定接收方没有收到M3但接着收到了M4。显然,接收方不能确认M4,因为M4是收到的失序报文段。根据可靠传输原理,接收方可以什么都不做,也可以在适当时机发送一次对M2的确认。但按照快重传算法的规定,接收方应及时发送对M2的重复确认,这样做可以让 发送方及早知道报文段M3没有到达接收方。发送方接着发送了M5和M6。接收方收到这两个报文后,也还要再次发出对M2的重复确认。这样,发送方共收到了 接收方的四个对M2的确认,其中后三个都是重复确认。(4)快恢复:与快重传配合使用的还有快恢复算法,当发送方连续收到三个重复确认时,就执行“乘法减少”算法,把ssthresh门限设置为拥塞窗口cwnd的一半,但是接下去并不执行慢开始算法,而是将cwnd设置为ssthresh的大小,然后执行拥塞避免算法:因为如果网络出现拥塞的话,就不会收到好几个重复的确认,所以发送方现在认为网络可能没有出现拥塞,所以此时并不执行慢开始算法,而是执行拥塞避免算法。4、拥塞控制和流量控制的差别:(1)相同点:拥塞控制和流量控制的相同点都是控制丢包现象,实现机制都是让发送方发得慢一点。(2)不同点:① 拥塞控制是一个全局性的过程,防止过多的数据注入到网络中,造成网络拥塞② 流量控制指点对点通信量的控制,要做的就是控制发送端发送数据的速率,以便使接收端来得及接受。五,应用层应用层主要提供应用进程间的网络通信服务,完成用户请求的各种服务。一、http协议:http协议即超文本传输协议,基于TCP协议,用于从Web服务器传输超文本到本地浏览器的传送协议。http协议是无状态协议,自身不对请求和响应直接的通信状态进行保存,但有些场景下我们需要保存用户的登陆信息,所以引入了cookie 和 session 来管理状态。1、cookie 和 session 的区别:(1)保存位置与安全性:cookie保存在客户端,session保存在服务端,所以在安全性上面,cookie存在安全隐患,可以通过拦截或本地文件找到cookie后进行攻击,而session相对更加安全。因此,可以将登陆信息等重要信息存放为session中;其他信息如果需要保留,可以放在cookie中。(2)存储容量:单个cookie最大只允许4KB,一个站点最多保存20个Cookie;session没有大小限制,个数只跟服务器的内存大小有关。(3)有效期与实现机制:cookie可长期有效存在;session依赖于cookie,过期时间默认为-1,只需关闭窗口该 session 就会失效。每个客户端对应一个session ,客户端之间的 session 相互独立;cookie:cookie是一小段的文本信息,当客户端请求服务器时,如果服务器需要记录该用户状态,就在响应头中向客户端浏览器颁发一个Cookie,而客户端浏览器会把cookie保存起来。当再次请求该网站时,浏览器把请求的网站连同该cookie一起提交给服务器,服务器会检查该cookie,以此来辨认用户状态。session:当客户端请求服务器时,都会带上cookie,cookie里面一般都会有一个JSESSIONID,服务器就按照 JSESSIONID 来找到对应的 session;如果客户端请求不包含 JSESSIONID,则为此客户端创建session并生成相关联的JSESSIONID,并将这个JSESSIONID在本次响应中返回给客户端保存。客户端保存这个 JSESSIONID 的方式可以使用cookie机制。若浏览器禁用Cookie的话,可以通过 URL重写机制 将JSESSIONID传回服务器。2、一个完整的http请求是怎么样?即从输入网址到获得页面的过程:(1)解析url,获取 url 中包含的域名;(2)通过DNS系统查询域名对应的IP;DNS服务器大致分为三种类型:根DNS服务器、顶级域DNS服务器 和 权威DNS服务器,其中: 顶级域DNS服务器主要负责诸如com、org、net、edu、gov 等顶级域名。根DNS服务器存储了所有 顶级域DNS服务器的 IP 地址,可以通过根服务器找到顶级域服务器(例如:http://www.baidu.com,根服务器会返回所有维护 com 这个顶级域服务器的 IP 地址)。然后你任选其中一个顶级域服务器发送请求,该顶级域服务器拿到域名后能够给出负责当前域的权威服务器地址(以 baidu为例的话,顶级域服务器将返回所有负责 baidu 这个域的权威服务器地址)。接着任选其中一个权威服务器地址查询 的具体 IP 地址,最终权威服务器会返回给你具体的 IP 地址。此外,本地 DNS 服务器是具有缓存功能的,通常两天内的记录都会被缓存。所以,通过DNS系统查询域名对应的 IP 的具体步骤可以总结为:① 操作系统先查本地 hosts文件 中是否有记录,如果有,则直接返回相对应映射的IP地址。② 如果本地hosts文件中没有配置,则主机向自己的本地 DNS 服务器 发送查询报文,如果本地DNS服务器缓存中有,将直接返回结果③ 如果本地服务器缓存中没有,则从内置在内部的根服务器列表(全球13台,固定的IP地址)中选一个发送查询报文④ 根服务器解析域名中的后缀名,告诉本地服务器负责该后缀名的所有顶级服务器列表⑤ 本地服务器选择其中一个顶级域服务器发送查询请求,顶级域服务器拿到域名后继续解析,返回对应域的所有权威服务器列表⑥ 本地服务器再向返回的权威服务器发送查询报文,最终会从某一个权威服务器上得到具体的 IP 地址⑦ 主机返回结果IP(3)浏览器得到域名对应的IP地址之后,向服务器发起三次握手请求建立TCP链接;(4)TCP链接链接建立起来后,浏览器向服务器发送http请求,如果 html文件在缓存里,浏览器则直接返回, 如果没有,则去后台拿;① 浏览器首次加载资源成功时,服务器返回200,此时浏览器不仅将资源下载下来,而且把response的header(里面的date属性非常重要,用来计算第二次相同资源时当前时间和date的时间差)一并缓存;② 下一次加载资源时,首先要经过强缓存的处理,cache-control的优先级最高,比如cache-control:no-cache,就直接进入到协商缓存的步骤了,如果cache-control:max-age=xxx,就会先比较当前时间和上一次返回200时的时间差,如果没有超过max-age,命中强缓存,不发请求直接从本地缓存读取该文件(这里需要注意,如果没有cache-control,会取expires的值,来对比是否过期),过期的话会进入下一个阶段,协商缓存③ 协商缓存阶段,则向服务器发送header带有If-None-Match和If-Modified-Since的请求,服务器会比较Etag,如果相同,命中协商缓存,返回304;如果不一致则有改动,直接返回新的资源文件带上新的Etag值并返回200;④ 协商缓存第二个重要的字段是,If-Modified-Since,如果客户端发送的If-Modified-Since的值跟服务器端获取的文件最近改动的时间,一致则命中协商缓存,返回304;不一致则返回新的last-modified和文件并返回200;(5)服务器接收到请求后,根据路径参数映射到特定的处理器进行处理,并将处理结果以及相应的视图返回给浏览器。(6)浏览器解析视图,并根据请求到的资源、数据进行渲染页面,最终向用户呈现一个完整的页面。构建DOM树(DOM tree):从上到下解析HTML文档生成DOM节点树(DOM tree),也叫内容树(content tree);构建CSSOM(CSS Object Model)树:加载解析样式生成CSSOM树;执行JavaScript:加载并执行JavaScript代码(包括内联代码或外联JavaScript文件);构建渲染树(render tree):根据DOM树和CSSOM树,生成渲染树(render tree);渲染树:按顺序展示在屏幕上的一系列矩形,这些矩形带有字体,颜色和尺寸等视觉属性。布局(layout):根据渲染树将节点树的每一个节点布局在屏幕上的正确位置;绘制(painting):遍历渲染树绘制所有节点,为每一个节点适用对应的样式,这一过程是通过UI后端模块完成;3、http的长连接和短连接?http的长连接和短连接本质上是TCP长连接和短连接。从http1.1开始就默认使用长连接。短链接是指客户端与服务端每进行一次请求操作,就建立一次TCP连接,收到服务器响应后,就断开连接。长连接是指客户端和服务建立TCP连接后,它们之间的连接会持续存在,不会因为一次HTTP请求后关闭,后续的请求也是用这个连接进行通信,使用长连接的HTTP协议,会在响应头有加入:Connection:keep-alive。长连接可以省去每次TCP建立和关闭的握手和挥手操作,节约时间提高效率。但在长连接下,客户端一般不会主动关闭连接,如果客户端和服务端之间的连接一直不关闭的话,随着连接数越来越多,会对服务端造成压力。所以长连接多用于频繁请求资源,而且连接数不能太多的情况,例如数据库的连接用长连接。而像Web网站这种并发量大,但是每个用户无需频繁操作的场景,一般都使用短连接,因为长连接对服务端来说会耗费一定的资源。4、http的断点续传是如何实现的?HTTP请求头有个Range字段;我们下载文件的时候如果遇到网络中断,如果重头开始下载会浪费时间,所以我们可以从上一次中断处继续开始下载;具体的操作:Range: bytes=5001-10000或者指定5001以后的所有数据Range: bytes=5001-5、http存在的问题:通信使用明文不加密,通信内容可能被窃听;无法验证报文的完整性,数据内容可能被篡改不验证通信方身份、可能遭到伪装,无法保证数据发送到正确的机器上;为了解决上述几个问题,那么就引入了https协议。二、https协议:https 是基于tcp协议,在http的基础上加入了SSL/TLS,可看成是添加了加密和认证机制的http,使用对称加密、非对称加密、证书等技术进行进行客户端与服务端的数据加密传输,最终达到保证整个通信的安全性。对称加密指加密和解密都使用同一个密钥的方式,这种方式存在如何安全地将密钥发送对方的问题;非对称加密使用两个密钥,公钥加密则需要私钥解密,私钥加密则需要公钥解密。不能私钥加密,私钥解密。非对称加密不需要发送用来解密的私钥,所以可以保证安全性,但是和对称加密比起来,速度非常的慢,所以我们还是要用对称加密来传送消息,但对称加密所使用的密钥我们可以通过非对称加密的方式发送出去。1、https的认证加密过程?如何保证内容不会被篡改的?(1)https是基于tcp协议的,首先客户端会和服务端发起链接建立(2)服务端返回它的证书给客户端,证书中包含了服务端公钥S.pub、颁发机构和有效期等信息(3)客户端通过浏览器内置的根证书(内部包含CA机构的公钥C.pub)验证证书的合法性(4)客户端生成随机的对称加密密钥Z,然后通过服务端的公钥S.pub加密发送给服务端(5)客户端和服务端之后就通过对称加密密钥Z加密数据来进行http通信2、根证书如何保证签发的证书是安全有效的?(1)服务器会预先生成非对称加密密钥,私钥S.pri自己保留,而公钥S.pub则发送给CA进行签名认证(2)CA机构也会预先生成非对称加密密钥,其私钥C.pri用来对服务器的公钥S.pub进行签名,生成CA证书(3)CA机构将签名生成的CA证书返回给服务器,也就是前面服务端给客户端那个证书(4)因为CA机构比较权威,所以很多浏览器会内置包含它公钥C.pub的证书,称之为根证书,然后可以使用根证书来验证其颁发证书的合法性了在整个过程中,一共涉及2对公私密钥对,一对由服务器产生,主要用于加密,一对由CA产生,主要用于签名。3、为什么需要CA证书认证机构呢?CA证书是为了确保服务端的公钥是准确无误、没有被修改过的。虽然https是加密的,但是请求还是可以被拦截的,假设没有CA证书,如果服务器返回的包含公钥的包被攻击者截取,然后攻击者也生成一对公私钥,他将自己的公钥发给客户端。攻击者得到客户端数据后进行解密,然后再通过服务器的公钥加密发给服务器,这样数据就被攻击者获取到了。有了CA证书后,客户端根据内置的CA根证书,很容易识别出攻击者的公钥不合法,或者说攻击者的证书不合法。证书通常包含这些内容:(1) 服务端的公钥;(2) 证书发行者(CA)对证书的数字签名;(3) 证书所用的签名算法;(4) 证书发布机构、有效期、所有者的信息等其他信息三、http 的请求与响应:1、http的常见请求方式:(1)get:向服务端获取资源,所以查询操作一般用get(2)post:向服务端提交请求字段,创建操作使用 post,该操作不是幂等的,多次执行会导致多条数据被创建(3)put:修改指定URL的资源,如果资源不存在,则进行创建,修改操作一般使用 put,在http中,put 被定义成幂等的,多次操作会导致前面的数据被覆盖(4)patch:局部修改URL所在资源的数据,是对put的补充(5)delete:删除指定URL的资源。(6)head:获取响应报文的首部,即获得URL资源的头部(7)options:询问服务器支持哪些方法,响应头中返回 Allow: GET、POST、HEAD(8)trace:追踪路径,主要用于测试或诊断;在请求头中在Max-Forwards字段设置数字,每经过一个服务器该数字就减一,当到0的时候就直接返回,一般通过该方法检查请求发送出去是否被篡改2、get和 post 请求的区别:(1)功能:get一般用来从服务器上面获取资源,post一般用来更新服务器上面的资源。(2)幂等性:get 是幂等的,post 为非幂等的(3)安全性:get 请求的参数会明文附加在URL之后,而 post 请求提交的数据则被封装到请求体中,相对更安全。(4)传输数据量的大小:get请求允许发送的数据量比较小,大多数浏览器都会限制请求的url长度在2048个字节,而大多数服务器最多处理64K大小的url;而post请求提交的数据量则是没有大小限制的。(5)参数的数据类型:GET只接受ASCII字符,而POST没有限制。(6)GET在浏览器回退时是无害的,而POST会再次提交请求。(7)get请求可以被缓存,可以被保留在浏览器的历史记录中;post请求不会被缓存,不会被保留在浏览器的历史记录中。3、http报文头分析:(1)报文类型:报文类型分为请求报文和响应报文① 请求报文包含三部分:请求行:包含请求方法、URI、HTTP版本信息请求首部字段请求内容实体② 响应报文包含三部分:状态行:包含HTTP版本、状态码、状态码的原因短语响应首部字段响应内容实体(2)报文中各部分的简要描述:方法(method):客户端希望服务器对资源执行的动作,是一个单独的词,比如:get 或者 post请求URL(request-URL):请求URL是资源的绝对路径,服务器可以假定自己是URL的主机/端口版本(version):报文所使用的Http版本,其格式:HTTP/<主要版本号>.<次要版本号>状态码(status-code):标识请求过程中所发生的情况原因短语(reason-phrase):数字状态码的可读版本,包含行终止序列之前的所有文本。请求头部(header):可以有零个或多个头部,每个首部都包含一个名字,后面跟着一个冒号(:),然后是一个可选的空格,接着是一个值,最后是一个CRLF首部是由一个空行(CRLF)结束的,表示了头部列表的结束和实体主体部分的开始实体的主体部分(entity-body):实体的主体部分包含一个由任意数据组成的数据块,并不是所有的报文都包含实体的主体部分,有时,报文只是以一个CRLF结束。(3)通用头部:既可以出现在请求报文中,也可以出现在响应报文中,它提供了与报文相关的最基本的信息:Connection:允许客户端和服务器指定与请求/响应连接有关的选项,http1.1之后默认是 keep-aliveDate:日期和时间标志,说明报文是什么时间创建的Transfer-Encoding:告知接收端为了保证报文的可靠传输,对报文采用了什么编码方式Cache-Control:用于随报文传送缓存指示(4)请求头部:请求头部是只在请求报文中有意义的头部。用于说明是谁或什么在发送请求、请求源自何处,或者客户端的喜好及能力Host:给出了接收请求的服务器的主机名和端口号Referer:提供了包含当前请求URI的文档的URLUser-Agent:将发起请求的应用程序名称告知服务器Accept:告诉服务器能够发送哪些媒体类型Accept-Encoding:告诉服务器能够发送哪些编码方式Accept-Language:告诉服务器能够发送哪些语言Range:如果服务器支持范围请求,就请求资源的指定范围If-Range:允许对文档的某个范围进行条件请求Authorization:包含了客户端提供给服务器,以便对其自身进行认证的数据Cookie:客户端用它向服务器传送数据(5)响应头部:响应头部为客户端提供了一些额外信息,比如谁在发送响应、响应者的功能,甚至与响应相关的一些特殊指令Age:(从最初创建开始)响应持续时间Server:服务器应用程序软件的名称和版本Accept-Ranges:对此资源来说,服务器可接受的范围类型Set-Cookie:在客户端设置数据,以便服务器对客户端进行标识(6)实体首部:描述主体的长度和内容,或者资源自身Allow:列出了可以对此实体执行的请求方法Location:告知客户端实体实际上位于何处,用于将接收端定向到资源的位置(URL)上去Content-Base:解析主体中的相对URL时使用的基础URLContent-Encoding:对主体执行的任意编码方式Content-Language:理解主体时最适宜使用的自然语言Content-Length:主体的长度Content-Type:这个主体的对象类型ETag:与此实体相关的实体标记Last-Modified:这个实体最后一次被修改的日期和时间(7)实体的主体部分:该部分其实就是HTTP要传输的内容,是可选的。HTTP报文可以承载很多类型的数字数据,比如,图片、视频、HTML文档电子邮件、软件应用程序等等。4、Http 常见的状态码:(1)1xx:请求处理中,请求已被接受,正在处理。(2)2xx:请求成功,请求被成功处理。200 :OK,客户端请求成功;204(请求处理成功,但是没有资源返回)(3)3xx:重定向,要完成请求必须进一步处理。301:永久性转移,请求的资源已经被分配到了新的地址302:暂时重定向304:已缓存。(4)4xx:客户端错误,请求不合法。400:客户端请求报文出现错误,通常是参数错误401:客户端未认证授权403:没有权限访问该资源404:未找到请求的资源405:不支持该请求方法,如果服务器支持GET,客户端用POST请求就会出现这个错误码(5)5xx:服务端错误,服务端不能处理合法请求。500:服务器内部错误。503:服务不可用,一段时间后可能恢复正常。5、http/1.1和http/2.0的区别:(1)多路复用,做到同一个连接并发处理多个请求:HTTP2.0 使用了多路复用的技术,做到同一个连接并发处理多个请求,并发请求的数量比HTTP1.1大了好几个数量级。(2)支持首部压缩:HTTP2.0使用HPACK算法对header的数据进行压缩,这样数据体积小了,在网络上传输就会更快。(3)服务器推送:当向支持HTTP2.0的web服务器请求时,服务器会顺便把客户端需要的资源一起推送到客户端,避免客户端再次创建连接发送请求到服务器端获取,这种方式非常合适加载静态资源。(4)http2.0采用二进制而不是文本格式6、http 和 https 的区别:(1)http 和 https 都是基于 TCP 协议,但是 http 是使用明文传输,通讯内容可能被窃听和篡改,客户端也无法验证通讯方的身份,无法保证数据发送到正确的机器上;https 是在 http 的基础上加入了 SSL/TLS,可看成是添加了加密和认证机制的http,使用对称加密、非对称加密、证书等技术进行进行客户端与服务端的数据加密传输,最终达到保证整个通信的安全性。(2)端口不同:http 使用的是80端口,https 使用的443端口(3)资源消耗:和 http 通信相比,https通信会由于加解密处理消耗更多的CPU和内存资源四、应用层其他相关的协议:(1)DNS域名系统:用于域名解析服务,将域名地址转换为IP地址,基于UDP服务,使用53端口。DNS底层既使用TCP又使用UDP协议:① 域名解析时使用UDP协议:客户端向DNS服务器查询域名,一般返回的内容都不超过512字节,用UDP传输即可,不用经过TCP三次握手,这样DNS服务器负载更低,响应更快。② 区域传送时使用TCP,主要有一下两点考虑:辅域名服务器会定时(一般时3小时)向主域名服务器进行查询以便了解数据是否有变动。如有变动,则会执行一次区域传送,进行数据同步。区域传送将使用TCP而不是UDP,因为数据同步传送的数据量比一个请求和应答的数据量要多得多。TCP是一种可靠的连接,保证了数据的准确性。(2)FTP:定义了文件传输协议,使用21端口。上传下载文件,都要用到FTP服务。(3)Telnet:远程终端协议,它是一种用于远程登陆的端口,用户可以以自己的身份远程连接到计算机上,提供一种基于DOS模式下的通信服务。(4)SMTP:定义了简单邮件传送协议,用于发送邮件,使用25号端口。(5)POP3:与SMTP对应,POP3用于接收邮件。使用110端口。(6)SNMP:简单网络管理协议,使用161号端口,是用来管理网络设备的。(7)TFTP(Trival File Transfer Protocal):简单文件传输协议,该协议在69端口上使用UDP服务。编辑于 2022-05-05 00:34编程语言编程计算机网络​赞同 7​​1 条评论​分享​喜欢​收藏​申请转载​文章被以下专栏收录网络协议栈专题发送端把信息通过规定好的协议进行

C语言网络编程-CSDN博客

>

C语言网络编程-CSDN博客

C语言网络编程

最新推荐文章于 2023-12-31 21:39:04 发布

酉酉囧

最新推荐文章于 2023-12-31 21:39:04 发布

阅读量1.9w

收藏

199

点赞数

43

分类专栏:

其他

文章标签:

c

socket

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

本文链接:https://blog.csdn.net/qq_41725312/article/details/90375742

版权

其他

专栏收录该内容

4 篇文章

1 订阅

订阅专栏

文章目录

套接字Linux下的套接字Windows下的套接字建立Socketbind() 函数connect() 函数linsten() 函数accept() 函数Linux 接受和发送数据Windos 接受和发送数据

示例WindowsLinux

参考

套接字

socket,套接字,它是计算机之间进行通信的一种约定或一种方式。通过 socket 这种约定,一台计算机可以接收其他计算机的数据,也可以向其他计算机发送数据。

Linux下的套接字

Linux中创建的文件都有一个 int 类型的编号,称为文件描述符(File Descriptor)。使用文件时,只要知道文件描述符就可以。socket 也被认为是文件的一种,和普通文件的操作没有区别

Windows下的套接字

WinSock(Windows Socket)编程依赖于系统提供的动态链接库(DLL),有两个版本:

较早的DLL是 wsock32.dll,大小为 28KB,对应的头文件为 winsock1.h;最新的DLL是 ws2_32.dll,大小为 69KB,对应的头文件为 winsock2.h。

加载ws2_32.dll

#pragma comment (lib, "ws2_32.lib")

WSAStartup()

使用DLL之前,还需要调用 WSAStartup() 函数进行初始化,以指明 WinSock 规范的版本

int WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData);

wVersionRequested 为 WinSock 规范的版本号,低字节为主版本号,高字节为副版本号(修正版本号)lpWSAData 为指向 WSAData 结构体的指针。

eg:

WSADATA wsaData;

WSAStartup(MAKEWORD(2, 2), &wsaData);

建立Socket

Linux

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

af ,地址族(Address Family),常用AF_INET(IPv4) 和 AF_INET6(IPv6)。type ,数据传输方式,常用的有 SOCK_STREAM(面向连接)和 SOCK_DGRAM(无连接)protocol 表示传输协议,常用的有 IPPROTO_TCP(TCP协议) 和 IPPTOTO_UDP(UDP协议)

1.TCP socket

int tcp_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

2.UDP socket

int udp_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);

Windows

SOCKET sock = socket(AF_INET, SOCK_STREAM, 0); //创建TCP套接字

bind() 函数

将套接字与特定的IP地址和端口绑定起来

int bind(int sock, struct sockaddr *addr, socklen_t addrlen); //Linux

int bind(SOCKET sock, const struct sockaddr *addr, int addrlen); //Windows

示例

//创建套接字

int serv_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

//创建sockaddr_in结构体变量

struct sockaddr_in serv_addr;

memset(&serv_addr, 0, sizeof(serv_addr)); //每个字节都用0填充

serv_addr.sin_family = AF_INET; //使用IPv4地址

serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); //具体的IP地址

serv_addr.sin_port = htons(1234); //端口

//将套接字和IP、端口绑定

bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));

1、sockaddr_in 结构体

struct sockaddr_in{

sa_family_t sin_family; //地址族(Address Family),也就是地址类型

uint16_t sin_port; //16位的端口号

struct in_addr sin_addr; //32位IP地址

char sin_zero[8]; //不使用,一般用0填充

};

sin_family 和 socket() 的第一个参数的含义相同,取值也要保持一致。 sin_prot 为端口号。需要用 htons() 函数转换 sin_addr 是 struct in_addr 结构体类型的变量 in_addr 结构体 struct in_addr{

in_addr_t s_addr; //32位的IP地址

};

需要inet_addr()转换 serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");

2、sockaddr

bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));

bind() 第二个参数的类型为 sockaddr,而代码中却使用 sockaddr_in,然后再强制转换为 sockaddr,这是为什么呢?

sockaddr 结构体的定义如下:

struct sockaddr{

sa_family_t sin_family; //地址族(Address Family),也就是地址类型

char sa_data[14]; //IP地址和端口号

};

下图是 sockaddr 与 sockaddr_in 的对比(括号中的数字表示所占用的字节数):

sockaddr 和 sockaddr_in 的长度相同,都是16字节,只是将IP地址和端口号合并到一起,用一个成员 sa_data 表示。要想给 sa_data 赋值,必须同时指明IP地址和端口号,例如”127.0.0.1:80“,遗憾的是,没有相关函数将这个字符串转换成需要的形式,也就很难给 sockaddr 类型的变量赋值,所以使用 sockaddr_in 来代替。这两个结构体的长度相同,强制转换类型时不会丢失字节,也没有多余的字节。

connect() 函数

建立连接

与bind类似

int connect(int sock, struct sockaddr *serv_addr, socklen_t addrlen); //Linux

int connect(SOCKET sock, const struct sockaddr *serv_addr, int addrlen); //Windows

linsten() 函数

套接字进入被动监听状态

int listen(int sock, int backlog); //Linux

int listen(SOCKET sock, int backlog); //Windows

sock 需要进入监听状态的套接字backlog 请求队列的最大长度

accept() 函数

套接字处于监听状态时,接收客户端请求,返回新的套接字

int accept(int sock, struct sockaddr *addr, socklen_t *addrlen); //Linux

SOCKET accept(SOCKET sock, struct sockaddr *addr, int *addrlen); //Windows

sock 为服务器端套接字addr 为 sockaddr_in 结构体变量addrlen 为参数 addr 的长度,可由 sizeof() 求得

Linux 接受和发送数据

write()

写入数据

ssize_t write(int fd, const void *buf, size_t nbytes);

fd 为要写入的文件的描述符buf 为要写入的数据的缓冲区地址nbytes 为要写入的数据的字节数。

read()

读取数据

ssize_t read(int fd, void *buf, size_t nbytes);

fd 为要读取的文件的描述符buf 为要接收数据的缓冲区地址nbytes 为要读取的数据的字节数。

Windos 接受和发送数据

send()

发送数据

int send(SOCKET sock, const char *buf, int len, int flags);

sock 为要发送数据的套接字buf 为要发送的数据的缓冲区地址len 为要发送的数据的字节数flags 为发送数据时的选项,一般设置为 0 或 NULL

recv()

接受数据

int recv(SOCKET sock, char *buf, int len, int flags);

同上

示例

Windows

server

#include

#include

#pragma comment (lib, "ws2_32.lib") //加载 ws2_32.dll

int main(){

//初始化 DLL

WSADATA wsaData;

WSAStartup(MAKEWORD(2, 2), &wsaData);

//创建套接字 PF_INET:IPv4

SOCKET servSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);

//绑定套接字

sockaddr_in sockAddr;

memset(&sockAddr, 0, sizeof(sockAddr)); //每个字节都用0填充

sockAddr.sin_family = PF_INET; //使用IPv4地址

sockAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); //具体的IP地址

sockAddr.sin_port = htons(1234); //端口

bind(servSock, (SOCKADDR*)&sockAddr, sizeof(SOCKADDR));

//进入监听状态

listen(servSock, 20);

//接收客户端请求

SOCKADDR clntAddr;

int nSize = sizeof(SOCKADDR);

SOCKET clntSock = accept(servSock, (SOCKADDR*)&clntAddr, &nSize);

//向客户端发送数据

char *str = "Hello World!";

send(clntSock, str, strlen(str)+sizeof(char), NULL);

//关闭套接字

closesocket(clntSock);

closesocket(servSock);

//终止 DLL 的使用

WSACleanup();

return 0;

}

client

#include

#include

#include

#pragma comment(lib, "ws2_32.lib")

//加载 ws2_32.dll

int main(){

//初始化DLL

WSADATA wsaData;

WSAStartup(MAKEWORD(2, 2), &wsaData);

//创建套接字

SOCKET sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);

//向服务器发起请求

sockaddr_in sockAddr;

memset(&sockAddr, 0, sizeof(sockAddr)); //每个字节都用0填充

sockAddr.sin_family = PF_INET;

sockAddr.sin_addr.s_addr = inet_addr("127.0.0.1");

sockAddr.sin_port = htons(1234);

connect(sock, (SOCKADDR*)&sockAddr, sizeof(SOCKADDR));

//接收服务器传回的数据

char szBuffer[MAXBYTE] = {0};

recv(sock, szBuffer, MAXBYTE, NULL);

//输出接收到的数据

printf("Message form server: %s\n", szBuffer);

//关闭套接字

closesocket(sock);

//终止使用 DLL

WSACleanup();

system("pause");

return 0;

Linux

服务器端代码 server.cpp

#include

#include

#include

#include

#include

#include

#include

int main(){

//创建套接字

int serv_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

//将套接字和IP、端口绑定

struct sockaddr_in serv_addr;

memset(&serv_addr, 0, sizeof(serv_addr)); //每个字节都用0填充

serv_addr.sin_family = AF_INET; //使用IPv4地址

serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); //具体的IP地址

serv_addr.sin_port = htons(1234); //端口

bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));

//进入监听状态,等待用户发起请求

listen(serv_sock, 20);

//接收客户端请求

struct sockaddr_in clnt_addr;

socklen_t clnt_addr_size = sizeof(clnt_addr);

int clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_addr_size);

//向客户端发送数据

char str[] = "Hello World!";

write(clnt_sock, str, sizeof(str));

//关闭套接字

close(clnt_sock);

close(serv_sock);

return 0;

}

客户端代码 client.cpp:

#include

#include

#include

#include

#include

#include

int main(){

//创建套接字

int sock = socket(AF_INET, SOCK_STREAM, 0);

//向服务器(特定的IP和端口)发起请求

struct sockaddr_in serv_addr;

memset(&serv_addr, 0, sizeof(serv_addr)); //每个字节都用0填充

serv_addr.sin_family = AF_INET; //使用IPv4地址

serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); //具体的IP地址

serv_addr.sin_port = htons(1234); //端口

connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));

//读取服务器传回的数据

char buffer[40];

read(sock, buffer, sizeof(buffer)-1);

printf("Message form server: %s\n", buffer);

//关闭套接字

close(sock);

return 0;

}

参考

C语言网络编程_C语言中文网

优惠劵

酉酉囧

关注

关注

43

点赞

199

收藏

觉得还不错?

一键收藏

知道了

4

评论

C语言网络编程

文章目录套接字Windows下的套接字Linux下的套接字Socketbind() 函数connect() 函数linsten() 函数accept() 函数Linux 接受和发送数据Windos 接受和发送数据示例WindowsLinux参考套接字socket,套接字,它是计算机之间进行通信的一种约定或一种方式。通过 socket 这种约定,一台计算机可以接收其他计算机的数据,也可以向其他...

复制链接

扫一扫

专栏目录

c语言网络编程-标准步骤(改进版)

09-04

主要介绍了c语言网络编程-标准步骤的改进说明,需要的朋友可以参考下

C语言网络编程——课程设计文档

03-21

NULL

博文链接:https://wanghailiang.iteye.com/blog/930515

4 条评论

您还未登录,请先

登录

后发表或查看评论

C语言基础知识(5):TCP网络编程

weixin_55238862的博客

12-31

934

TCP 是面向连接的、可靠的流协议。流就是指不间断的数据结构,当应用程序采用 TCP 发送消息时,虽然可以保证发送的顺序,但还是犹如没有任何间隔的数据流发送给接收端。TCP 为提供可靠性传输,实行“顺序控制”或“重发控制”机制。此外还具备“流控制(流量控制)”、“拥塞控制”、提高网络利用率等众多功能。

ftp传输---c语言网络编程

09-27

自己写的c语言通过网络传输文件,有获取、发送、显示目录、 删除。可以自己增加功能。。。。。。。。。。。。。。。。。。。。。。。

c语言网络编程-标准步骤(比较简单)

01-21

c语言网络编程-标准步骤,真的很简单啊

server.c

代码如下:#include #include #include #include #include #include #include #include #define PORT 4444#define BACKLOG 5int main(int argc, char *argv[]) {    int sock_fd, new_fd;    stru

C语言网络编程快速入门

01-11

C语言网络编程快速入门

C语言的学习,一般的方式是:先学C,然后是C++,

最好还要有汇编语言和微机原理基础,然后才是Visual

C++。这样的方式,对学习者来说,要花费很多时间和

精力。而在学校教学中,也就没有时间深入学习Win—

dows编程的实用技术了。

其实,具有了C语言基础后,再有一些基本的C++

类的概念,就可以直接学习Windows C编程了。

C语言网络编程——基础

Stars____的博客

04-28

7483

OSI七层参考模型

是理想化的并没有完全实现的模型。

应用层

提供响应的应用服务

表示层

数据的表示和加密

会话层

建立会话关系

传输层

通过传输协议传输数据

网络层

实现跨子网通信,路由转发,维护路由表。

数据链路层

实现以太网内数据帧的转发

物理层

按照一定的传输规则传输电信号。

TCP/IP 四层模型

详细介绍见https://blog.csdn.net/Stars____/article/details/108694074

SCTP协议:TCP的升级版

TCP/IP 网络编程

unix域套接字:用于

C语言之网络编程(必背知识点)

qq_52049228的博客

05-27

3991

提供了一个面向连接、可靠的数据传输服务,数据无差错、无重复的发送且按发送顺序接收。内设置流量控制,避免数据流淹没慢的接收方。数据被看作是字节流,无长度限制。

什么是网络编程,C 语言中如何进行网络编程?C 语言中如何进行数据库编程?

fengyege的博客

07-23

617

网络编程是指使用计算机网络进行数据传输和通信的编程技术。它涉及到服务器和客户端之间的数据交换和通信。在C语言中,网络编程可以通过使用套接字(socket)库来实现。套接字是一种用于网络通信的抽象,它提供了一组函数和数据结构,可以在应用程序之间进行网络通信。以下是C语言中进行网络编程的基本步骤:创建套接字:使用socket()函数创建一个套接字。

C语言动态获取设备的网络接口名称和状态以及对应的IP地址

coderma的博客

07-13

839

C语言动态获取设备的网络接口名称和状态以及对应的IP地址

linux C语言 网络编程教程及源码

05-12

linux C语言 网络编程教程及源码

一、网络应用层编程

1、Linux网络编程01——网络协议入门

2、Linux网络编程02——无连接和面向连接的区别

3、Linux网络编程03——字节序和地址转换

4、Linux网络编程04——套接字

5、Linux网络编程05——C/S与B/S架构的区别

6、Linux网络编程06——UDP协议编程

7、Linux网络编程07——广播

8、Linux网络编程08——多播

9、Linux网络编程09——TCP编程之客户端

10、Linux网络编程10——TCP编程之服务器

11、Linux网络编程11——tcp、udp迭代服务器

12、Linux网络编程12——tcp三次握手、四次挥手

13、Linux网络编程13——connect()、listen()和accept()三者之间的关系

14、Linux网络编程14——I/O复用之select详解

15、Linux网络编程15——I/O复用之poll详解

16、Linux网络编程16——I/O复用之epoll详解

17、Linux网络编程17——tcp并发服务器(多进程)

18、Linux网络编程18——tcp并发服务器(多线程)

19、Linux网络编程——tcp高效并发服务器(select实现)

20、Linux网络编程——tcp高效并发服务器(poll实现)

21、Linux网络编程——tcp高效并发服务器(epoll实现)

二、网络底层编程(黑客模式)

1、Linux网络编程1——啥叫原始套接字

2、Linux网络编程2——原始套接字编程

3、Linux网络编程3——原始套接字实例:MAC头分析

4、Linux网络编程4——原始套接字实例:MAC地址扫描器

5、Linux网络编程5——IP数据报格式详解

6、Linux网络编程6——TCP、UDP数据包格式详解

7、Linux网络编程7——原始套接字实例:发送UDP数据包

8、Linux网络编程8——libpcap详解

9、Linux网络编程9——libnet详解

简析Windows C语言网络编程技术与方法.pdf

09-19

简析Windows C语言网络编程技术与方法.pdf

windows下的C语言网络编程.pdf

03-21

windows下的C语言网络编程.pdfwindows下的C语言网络编程.pdfwindows下的C语言网络编程.pdfwindows下的C语言网络编程.pdfwindows下的C语言网络编程.pdf

K8s 很难么?带你从头到尾捋一遍,不信你学不会

民工哥的博客

02-23

8559

点击关注公众号,回复“1024”获取2TB学习资源!为什么要学习 Kubernetes?虽然 Docker 已经很强大了,但是在实际使用上还是有诸多不便,比如集群管理、资源调度、文件管理等...

10天智能锁项目实战第1天(了解单片机STM32F401RET6和C语言基础)

北豼不太皮的博客

02-21

2898

10天智能锁项目实战第1天(了解单片机STM32F401RET6和C语言基础)一、学习目标二、了解单片机STM32F401RET6三、C语言基础

一、学习目标

二、了解单片机STM32F401RET6

4、STM32F401RE特征

三、C语言基础

1.数据类型

常用2的次方:

2^7 = 128

2^8 = 256

2^15 = 32768

2^16= 65536

51单片机常见的数据类型:

char: 占内存1字节 取值范围:-128~127 -2^7 ~ 2

Android开发(1) | Fragment 的应用——新闻应用

Jormungand_V的博客

02-21

3355

文章目录

news_item.xml:

xmlns:android="http://schemas.android.com/apk/res/android"

android:id="@+id/news_title"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:lines="1"

android:ellipsize="

系统学习 TypeScript(四)——变量声明的初步学习

编程三昧

02-25

1349

认识了 TypeScript 中的基础类型,接下来当然是变量声明的相关学习了,我在这里记录一下我学习过程中的一些总结。

清除浮动的五种方法

weixin_52212950的博客

02-22

1913

为什么要清除浮动?因为往往浮动后的子元素因为脱离了标准流,不能自动撑起父元素的高度,所以会对后续布局产生影响,对此清除浮动不如理解为清除浮动产生的影响更为合理。

例如:我们设置了两个盒子如图所示,粉色为父盒子,只有宽度没有高度,蓝色盒子有宽有高,粉色盒子的高由蓝盒子的高度撑开。

但是给蓝色的子盒子设置了左浮动后,脱离了标准流,无法再撑开粉盒子,可以看到粉盒子高度变成了0;

清除浮动有五种方法:

直接设置父元素的高度

额外标签法

单伪元素法

双伪元素法

ove.

c语言网络编程如何组帧

最新发布

01-19

C语言网络编程中,组帧是将数据按照一定的格式打包成帧的过程。组帧的目的是为了在网络传输中能够准确地识别数据的起始和结束,并且能够正确地解析数据。

在C语言网络编程中,组帧通常包括以下步骤:

1. 定义帧格式:首先需要确定数据在网络中的传输格式,即帧的起始标志、数据长度、数据内容和校验码等信息。

2. 封装数据:根据定义的帧格式,将数据按照格式进行封装,将数据按照帧的格式组织成一个完整的帧。

3. 加入校验:为了保证数据的完整性和正确性,通常在帧中加入校验码,比如CRC校验,用于检测并纠正数据在传输中的错误。

4. 发送帧:封装完成的帧通过网络传输给接收端,接收端则需要进行帧的解析和处理。

总之,在C语言网络编程中,组帧是非常重要的一步,通过合理的组帧可以保证数据在网络中的正确传输,提高数据的可靠性和稳定性。

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

非常没帮助

没帮助

一般

有帮助

非常有帮助

提交

酉酉囧

CSDN认证博客专家

CSDN认证企业博客

码龄6年

暂无认证

41

原创

5万+

周排名

168万+

总排名

15万+

访问

等级

1649

积分

63

粉丝

127

获赞

32

评论

578

收藏

私信

关注

热门文章

仿射密码解析与实例

26669

C语言网络编程

19850

Oh My Zsh 强大炫酷的Shell

13688

Bugku web 管理员系统 write up

13245

yersinia工具的使用(vlan跳跃,stp攻击等)

10436

分类专栏

Crypto

2篇

write up

4篇

环境搭建

5篇

PHP审计

6篇

MySQL

2篇

Web

5篇

网络

4篇

Pyhton

12篇

其他

4篇

二进制安全

1篇

最新评论

macOS 12 pyenv 和 pyenv-virtualenv 安装和使用

Tobyllllllba:

你好想请问一下,没有配置shell环境可以直接下载python吗?我输入这个直接卡住了,不知道是不是在下载

tobylin@Tobys-Macbook ~ % pyenv install 3.8.10

python-build: use openssl from homebrew

python-build: use readline from homebrew

Downloading Python-3.8.10.tar.xz...

-> https://www.python.org/ftp/python/3.8.10/Python-3.8.10.tar.xz

网络嗅探dsniff套件的使用

what d:

请问作者大大urlsnarf可以嗅探手机吗?

yersinia工具的使用(vlan跳跃,stp攻击等)

今天也要加油^0^~:

您好 ,请问我的dhcp 地址耗尽攻击和dhcp欺骗不能同时运行,是内存不够,还是软件本身不兼容呢?

Python 协议攻击脚本(七): DHCP攻击

findriver:

只能在linux下用吗?Windows下没有效果

Python 协议攻击脚本(七): DHCP攻击

XINGDAREN:

用什么抓包呀

您愿意向朋友推荐“博客详情页”吗?

强烈不推荐

不推荐

一般般

推荐

强烈推荐

提交

最新文章

Swift 学习笔记

Spring heapdump 敏感信息查找

Python 打印菜单

2022年4篇

2020年2篇

2019年20篇

2018年17篇

目录

目录

分类专栏

Crypto

2篇

write up

4篇

环境搭建

5篇

PHP审计

6篇

MySQL

2篇

Web

5篇

网络

4篇

Pyhton

12篇

其他

4篇

二进制安全

1篇

目录

评论 4

被折叠的  条评论

为什么被折叠?

到【灌水乐园】发言

查看更多评论

添加红包

祝福语

请填写红包祝福语或标题

红包数量

红包个数最小为10个

红包总金额

红包金额最低5元

余额支付

当前余额3.43元

前往充值 >

需支付:10.00元

取消

确定

下一步

知道了

成就一亿技术人!

领取后你会自动成为博主和红包主的粉丝

规则

hope_wisdom 发出的红包

实付元

使用余额支付

点击重新获取

扫码支付

钱包余额

0

抵扣说明:

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

余额充值

有什么适合提高 C/C++ 网络编程能力的开源项目推荐? - 知乎

有什么适合提高 C/C++ 网络编程能力的开源项目推荐? - 知乎首页知乎知学堂发现等你来答​切换模式登录/注册开源软件编程C(编程语言)开源开源项目C++网络编程有什么适合提高 C/C++ 网络编程能力的开源项目推荐?关注者6,071被浏览2,354,772关注问题​写回答​邀请回答​好问题 166​2 条评论​分享​95 个回答默认排序知乎用户R26s0w​ 关注最值得你所关注的10个C语言开源项目1. WebbenchWebbench是一个在linux下使用的非常简单的网站压测工具。它使用fork()模拟多个客户端同时访问我们设定的URL,测试网站在压力下工作的性能,最多可以模拟3万个并发连接去测试网站的负载能力。Webbench使用C语言编写, 代码实在太简洁,源码加起来不到600行。下载链接:http://home.tiscali.cz/~cz210552/webbench.html 2. Tinyhttpdtinyhttpd是一个超轻量型Http Server,使用C语言开发,全部代码只有502行(包括注释),附带一个简单的Client,可以通过阅读这段代码理解一个 Http Server 的本质。下载链接:http://sourceforge.net/projects/tinyhttpd/3. cJSONcJSON是C语言中的一个JSON编解码器,非常轻量级,C文件只有500多行,速度也非常理想。cJSON也存在几个弱点,虽然功能不是非常强大,但cJSON的小身板和速度是最值得赞赏的。其代码被非常好地维护着,结构也简单易懂,可以作为一个非常好的C语言项目进行学习。项目主页:http://sourceforge.net/projects/cjson/4. CMockerycmockery是google发布的用于C单元测试的一个轻量级的框架。它很小巧,对其他开源包没有依赖,对被测试代码侵入性小。cmockery的源代码行数不到3K,你阅读一下will_return和mock的源代码就一目了然了。主要特点:免费且开源,google提供技术支持;轻量级的框架,使测试更加快速简单;避免使用复杂的编译器特性,对老版本的编译器来讲,兼容性好;并不强制要求待测代码必须依赖C99标准,这一特性对许多嵌入式系统的开发很有用下载链接:http://code.google.com/p/cmockery/downloads/list5. Libevlibev是一个开源的事件驱动库,基于epoll,kqueue等OS提供的基础设施。其以高效出名,它可以将IO事件,定时器,和信号统一起来,统一放在事件处理这一套框架下处理。基于Reactor模式,效率较高,并且代码精简(4.15版本8000多行),是学习事件驱动编程的很好的资源。下载链接:http://software.schmorp.de/pkg/libev.html6. MemcachedMemcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提供动态数据库驱动网站的速度。Memcached 基于一个存储键/值对的 hashmap。Memcached-1.4.7的代码量还是可以接受的,只有10K行左右。下载地址:http://memcached.org/ 7. LuaLua很棒,Lua是巴西人发明的,这些都令我不爽,但是还不至于脸红,最多眼红。让我脸红的是Lua的源代码,百分之一百的ANSI C,一点都不掺杂。在任何支持ANSI C编译器的平台上都可以轻松编译通过。我试过,真是一点废话都没有。Lua的代码数量足够小,5.1.4仅仅1.5W行,去掉空白行和注释估计能到1W行。下载地址:http://www.lua.org/8. SQLiteSQLite是一个开源的嵌入式关系数据库,实现自包容、零配置、支持事务的SQL数据库引擎。 其特点是高度便携、使用方便、结构紧凑、高效、可靠。足够小,大致3万行C代码,250K。下载地址:http://www.sqlite.org/ 。9. UNIX v6UNIX V6 的内核源代码包括设备驱动程序在内 约有1 万行,这个数量的源代码,初学者是能够充分理解的。有一种说法是一个人所能理解的代码量上限为1 万行,UNIX V6的内核源代码从数量上看正好在这个范围之内。看到这里,大家是不是也有“如果只有1万行的话没准儿我也能学会”的想法呢?另一方面,最近的操作系统,例如Linux 最新版的内核源代码据说超过了1000 万行。就算不是初学者,想完全理解全部代码基本上也是不可能的。下载地址:http://minnie.tuhs.org/cgi-bin/utree.pl?file=V610. NETBSDNetBSD是一个免费的,具有高度移植性的 UNIX-like 操作系统,是现行可移植平台最多的操作系统,可以在许多平台上执行,从 64bit alpha 服务器到手持设备和嵌入式设备。NetBSD计划的口号是:”Of course it runs NetBSD”。它设计简洁,代码规范,拥有众多先进特性,使得它在业界和学术界广受好评。由于简洁的设计和先进的特征,使得它在生产和研究方面,都有卓越的表现,而且它也有受使用者支持的完整的源代码。许多程序都可以很容易地通过NetBSD Packages Collection获得。下载地址:http://www.netbsd.org/C++ 资源大全关于 C++ 框架、库和资源的一些汇总列表,内容包括:标准库、Web应用框架、人工智能、数据库、图片处理、机器学习、日志、代码分析等。标准库C++标准库,包括了STL容器,算法和函数等。C++ Standard Library:是一系列类和函数的集合,使用核心语言编写,也是C++ISO自身标准的一部分。Standard Template Library:标准模板库C POSIX library : POSIX系统的C标准库规范ISO C++ Standards Committee :C++标准委员会框架C++通用框架和库Apache C++ Standard Library:是一系列算法,容器,迭代器和其他基本组件的集合ASL :Adobe源代码库提供了同行的评审和可移植的C++源代码库。Boost :大量通用C++库的集合。BDE :来自于彭博资讯实验室的开发环境。Cinder:提供专业品质创造性编码的开源开发社区。Cxxomfort:轻量级的,只包含头文件的库,将C++ 11的一些新特性移植到C++03中。Dlib:使用契约式编程和现代C++科技设计的通用的跨平台的C++库。EASTL :EA-STL公共部分ffead-cpp :企业应用程序开发框架Folly:由Facebook开发和使用的开源C++库JUCE :包罗万象的C++类库,用于开发跨平台软件libPhenom:用于构建高性能和高度可扩展性系统的事件框架。LibSourcey :用于实时的视频流和高性能网络应用程序的C++11 evented IOLibU : C语言写的多平台工具库Loki :C++库的设计,包括常见的设计模式和习语的实现。MiLi :只含头文件的小型C++库openFrameworks :开发C++工具包,用于创意性编码。Qt :跨平台的应用程序和用户界面框架Reason :跨平台的框架,使开发者能够更容易地使用Java,.Net和Python,同时也满足了他们对C++性能和优势的需求。ROOT :具备所有功能的一系列面向对象的框架,能够非常高效地处理和分析大量的数据,为欧洲原子能研究机构所用。STLport:是STL具有代表性的版本STXXL:用于额外的大型数据集的标准模板库。Ultimate++ :C++跨平台快速应用程序开发框架Windows Template Library:用于开发Windows应用程序和UI组件的C++库Yomm11 :C++11的开放multi-methods.人工智能btsk :游戏行为树启动器工具Evolving Objects:基于模板的,ANSI C++演化计算库,能够帮助你非常快速地编写出自己的随机优化算法。Neu:C++11框架,编程语言集,用于创建人工智能应用程序的多用途软件系统。异步事件循环Boost.Asio:用于网络和底层I/O编程的跨平台的C++库。libev :功能齐全,高性能的时间循环,轻微地仿效libevent,但是不再像libevent一样有局限性,也修复了它的一些bug。libevent :事件通知库libuv :跨平台异步I/O。音频音频,声音,音乐,数字化音乐库FMOD :易于使用的跨平台的音频引擎和音频内容的游戏创作工具。Maximilian :C++音频和音乐数字信号处理库OpenAL :开源音频库—跨平台的音频APIOpus:一个完全开放的,免版税的,高度通用的音频编解码器Speex:免费编解码器,为Opus所废弃Tonic: C++易用和高效的音频合成Vorbis: Ogg Vorbis是一种完全开放的,非专有的,免版税的通用压缩音频格式。生态学生物信息,基因组学和生物技术libsequence:用于表示和分析群体遗传学数据的C++库。SeqAn:专注于生物数据序列分析的算法和数据结构。Vcflib :用于解析和处理VCF文件的C++库Wham:直接把联想测试应用到BAM文件的基因结构变异。压缩压缩和归档库bzip2:一个完全免费,免费专利和高质量的数据压缩doboz:能够快速解压缩的压缩库PhysicsFS:对各种归档提供抽象访问的库,主要用于视频游戏,设计灵感部分来自于Quake3的文件子系统。KArchive:用于创建,读写和操作文件档案(例如zip和 tar)的库,它通过QIODevice的一系列子类,使用gzip格式,提供了透明的压缩和解压缩的数据。LZ4 :非常快速的压缩算法LZHAM :无损压缩数据库,压缩比率跟LZMA接近,但是解压缩速度却要快得多。LZMA :7z格式默认和通用的压缩方法。LZMAT :及其快速的实时无损数据压缩库miniz:单一的C源文件,紧缩/膨胀压缩库,使用zlib兼容API,ZIP归档读写,PNG写方式。Minizip:Zlib最新bug修复,支持PKWARE磁盘跨越,AES加密和IO缓冲。Snappy :快速压缩和解压缩ZLib :非常紧凑的数据流压缩库ZZIPlib:提供ZIP归档的读权限。并发性并发执行和多线程Boost.Compute :用于OpenCL的C++GPU计算库Bolt :针对GPU进行优化的C++模板库C++React :用于C++11的反应性编程库Intel TBB :Intel线程构件块Libclsph:基于OpenCL的GPU加速SPH流体仿真库OpenCL :并行编程的异构系统的开放标准OpenMP:OpenMP APIThrust :类似于C++标准模板库的并行算法库HPX :用于任何规模的并行和分布式应用程序的通用C++运行时系统VexCL :用于OpenCL/CUDA 的C++向量表达式模板库。容器C++ B-tree :基于B树数据结构,实现命令内存容器的模板库Hashmaps: C++中开放寻址哈希表算法的实现密码学Bcrypt :一个跨平台的文件加密工具,加密文件可以移植到所有可支持的操作系统和处理器中。BeeCrypt:Botan: C++加密库Crypto++:一个有关加密方案的免费的C++库GnuPG: OpenPGP标准的完整实现GnuTLS :实现了SSL,TLS和DTLS协议的安全通信库LibgcryptlibmcryptLibreSSL:免费的SSL/TLS协议,属于2014 OpenSSL的一个分支LibTomCrypt:一个非常全面的,模块化的,可移植的加密工具libsodium:基于NaCI的加密库,固执己见,容易使用Nettle 底层的加密库OpenSSL : 一个强大的,商用的,功能齐全的,开放源代码的加密库。Tiny AES128 in C :用C实现的一个小巧,可移植的实现了AES128ESB的加密算法数据库数据库,SQL服务器,ODBC驱动程序和工具hiberlite :用于Sqlite3的C++对象关系映射Hiredis: 用于Redis数据库的很简单的C客户端库LevelDB: 快速键值存储库LMDB:符合数据库四大基本元素的嵌入键值存储MySQL++:封装了MySql的C API的C++ 包装器RocksDB:来自Facebook的嵌入键值的快速存储SQLite:一个完全嵌入式的,功能齐全的关系数据库,只有几百KB,可以正确包含到你的项目中。调试调试库, 内存和资源泄露检测,单元测试Boost.Test:Boost测试库Catch:一个很时尚的,C++原生的框架,只包含头文件,用于单元测试,测试驱动开发和行为驱动开发。CppUnit:由JUnit移植过来的C++测试框架CTest:CMake测试驱动程序googletest:谷歌C++测试框架ig-debugheap:用于跟踪内存错误的多平台调试堆libtap:用C语言编写测试MemTrack —用于C++跟踪内存分配microprofile- 跨平台的网络试图分析器minUnit :使用C写的迷你单元测试框架,只使用了两个宏Remotery:用于web视图的单一C文件分析器UnitTest++:轻量级的C++单元测试框架游戏引擎Cocos2d-x :一个跨平台框架,用于构建2D游戏,互动图书,演示和其他图形应用程序。Grit :社区项目,用于构建一个免费的游戏引擎,实现开放的世界3D游戏。Irrlicht :C++语言编写的开源高性能的实时#D引擎Polycode:C++实现的用于创建游戏的开源框架(与Lua绑定)。图形用户界面CEGUI : 很灵活的跨平台GUI库FLTK :快速,轻量级的跨平台的C++GUI工具包。GTK+: 用于创建图形用户界面的跨平台工具包gtkmm :用于受欢迎的GUI库GTK+的官方C++接口。imgui:拥有最小依赖关系的立即模式图形用户界面libRocket :libRocket 是一个C++ HTML/CSS 游戏接口中间件MyGUI :快速,灵活,简单的GUINcurses:终端用户界面QCustomPlot :没有更多依赖关系的Qt绘图控件Qwt :用户与技术应用的Qt 控件QwtPlot3D :功能丰富的基于Qt/OpenGL的C++编程库,本质上提供了一群3D控件OtterUI :OtterUI 是用于嵌入式系统和互动娱乐软件的用户界面开发解决方案PDCurses 包含源代码和预编译库的公共图形函数库wxWidgets C++库,允许开发人员使用一个代码库可以为widows, Mac OS X,Linux和其他平台创建应用程序图形bgfx:跨平台的渲染库Cairo:支持多种输出设备的2D图形库Horde3D 一个小型的3D渲染和动画引擎magnum C++11和OpenGL 2D/3D 图形引擎Ogre 3D 用C++编写的一个面向场景,实时,灵活的3D渲染引擎(并非游戏引擎)OpenSceneGraph 具有高性能的开源3D图形工具包Panda3D 用于3D渲染和游戏开发的框架,用Python和C++编写。Skia 用于绘制文字,图形和图像的完整的2D图形库urho3d 跨平台的渲染和游戏引擎。图像处理Boost.GIL:通用图像库CImg :用于图像处理的小型开源C++工具包CxImage :用于加载,保存,显示和转换的图像处理和转换库,可以处理的图片格式包括 BMP, JPEG, GIF, PNG, TIFF, MNG, ICO, PCX, TGA, WMF, WBMP, JBG, J2K。FreeImage :开源库,支持现在多媒体应用所需的通用图片格式和其他格式。GDCM:Grassroots DICOM 库ITK:跨平台的开源图像分析系统Magick++:ImageMagick程序的C++接口MagickWnd:ImageMagick程序的C++接口OpenCV : 开源计算机视觉类库tesseract-ocr:OCR引擎VIGRA :用于图像分析通用C++计算机视觉库VTK :用于3D计算机图形学,图像处理和可视化的开源免费软件系统。国际化gettext :GNU `gettext’IBM ICU:提供Unicode 和全球化支持的C、C++ 和Java库libiconv :用于不同字符编码之间的编码转换库Jasonfrozen : C/C++的Jason解析生成器Jansson :进行编解码和处理Jason数据的C语言库jbson :C++14中构建和迭代BSON data,和Json 文档的库JeayeSON:非常健全的C++ JSON库,只包含头文件JSON++ : C++ JSON 解析器json-parser:用可移植的ANSI C编写的JSON解析器,占用内存非常少json11 :一个迷你的C++11 JSON库jute :非常简单的C++ JSON解析器ibjson:C语言中的JSON解析和打印库,很容易和任何模型集成。libjson:轻量级的JSON库PicoJSON:C++中JSON解析序列化,只包含头文件qt-json :用于JSON数据和 QVariant层次间的相互解析的简单类QJson:将JSON数据映射到QVariant对象的基于Qt的库RapidJSON: 用于C++的快速JSON 解析生成器,包含SAX和DOM两种风格的APIYAJL :C语言中快速流JSON解析库日志Boost.Log :设计非常模块化,并且具有扩展性easyloggingpp:C++日志库,只包含单一的头文件。Log4cpp :一系列C++类库,灵活添加日志到文件,系统日志,IDSA和其他地方。templog:轻量级C++库,可以添加日志到你的C++应用程序中机器学习Caffe :快速的神经网络框架CCV :以C语言为核心的现代计算机视觉库mlpack :可扩展的C++机器学习库OpenCV:开源计算机视觉库Recommender:使用协同过滤进行产品推荐/建议的C语言库。SHOGUN:Shogun 机器学习工具sofia-ml :用于机器学习的快速增量算法套件数学Armadillo :高质量的C++线性代数库,速度和易用性做到了很好的平衡。语法和MatlAB很相似blaze:高性能的C++数学库,用于密集和稀疏算法。ceres-solver :来自谷歌的C++库,用于建模和解决大型复杂非线性最小平方问题。CGal: 高效,可靠的集合算法集合cml :用于游戏和图形的免费C++数学库Eigen :高级C++模板头文件库,包括线性代数,矩阵,向量操作,数值解决和其他相关的算法。GMTL:数学图形模板库是一组广泛实现基本图形的工具。GMP:用于个高精度计算的C/C++库,处理有符号整数,有理数和浮点数。多媒体GStreamer :构建媒体处理组件图形的库LIVE555 Streaming Media :使用开放标准协议(RTP/RTCP, RTSP, SIP) 的多媒体流库libVLC :libVLC (VLC SDK)媒体框架QtAv:基于Qt和FFmpeg的多媒体播放框架,能够帮助你轻而易举地编写出一个播放器SDL :简单直控媒体层SFML :快速,简单的多媒体库网络ACE:C++面向对象网络变成工具包Boost.Asio:用于网络和底层I/O编程的跨平台的C++库Casablanca:C++ REST SDKcpp-netlib:高级网络编程的开源库集合Dyad.c:C语言的异步网络libcurl :多协议文件传输库Mongoose:非常轻量级的网络服务器Muduo :用于Linux多线程服务器的C++非阻塞网络库net_skeleton :C/C++的TCP 客户端/服务器库nope.c :基于C语言的超轻型软件平台,用于可扩展的服务器端和网络应用。 对于C编程人员,可以考虑node.jsOnion :C语言HTTP服务器库,其设计为轻量级,易使用。POCO:用于构建网络和基于互联网应用程序的C++类库,可以运行在桌面,服务器,移动和嵌入式系统。RakNet:为游戏开发人员提供的跨平台的开源C++网络引擎。Tuf o :用于Qt之上的C++构建的异步Web框架。WebSocket++ :基于C++/Boost Aiso的websocket 客户端/服务器库ZeroMQ :高速,模块化的异步通信库物理学动力学仿真引擎Box2D:2D的游戏物理引擎。Bullet :3D的游戏物理引擎。Chipmunk :快速,轻量级的2D游戏物理库LiquidFun:2D的游戏物理引擎ODE :开放动力学引擎-开源,高性能库,模拟刚体动力学。ofxBox2d:Box2D开源框架包装器。Simbody :高性能C++多体动力学/物理库,模拟关节生物力学和机械系统,像车辆,机器人和人体骨骼。机器人学MOOS-IvP :一组开源C++模块,提供机器人平台的自主权,尤其是自主的海洋车辆。MRPT:移动机器人编程工具包PCL :点云库是一个独立的,大规模的开放项目,用于2D/3D图像和点云处理。Robotics Library (RL): 一个独立的C++库,包括机器人动力学,运动规划和控制。RobWork:一组C++库的集合,用于机器人系统的仿真和控制。ROS :机器人操作系统,提供了一些库和工具帮助软件开发人员创建机器人应用程序。科学计算FFTW :用一维或者多维计算DFT的C语言库。GSL:GNU科学库。脚本ChaiScript :用于C++的易于使用的嵌入式脚本语言。Lua :用于配置文件和基本应用程序脚本的小型快速脚本引擎。luacxx:用于创建Lua绑定的C++ 11 APISWIG :一个可以让你的C++代码链接到JavaScript,Perl,PHP,Python,Tcl和Ruby的包装器/接口生成器V7:嵌入式的JavaScript 引擎。V8 :谷歌的快速JavaScript引擎,可以被嵌入到任何C++应用程序中。序列化Cap’n Proto :快速数据交换格式和RPC系统。cereal :C++11 序列化库FlatBuffers :内存高效的序列化库MessagePack :C/C++的高效二进制序列化库,例如 JSONprotobuf :协议缓冲,谷歌的数据交换格式。protobuf-c :C语言的协议缓冲实现SimpleBinaryEncoding:用于低延迟应用程序的对二进制格式的应用程序信息的编码和解码。Thrift :高效的跨语言IPC/RPC,用于C++,Java,Python,PHP,C#和其它多种语言中,最初由Twitter开发。视频libvpx :VP8/VP9编码解码SDKFFmpeg :一个完整的,跨平台的解决方案,用于记录,转换视频和音频流。libde265 :开放的h.265视频编解码器的实现。OpenH264:开源H.364 编解码器。Theora :免费开源的视频压缩格式。虚拟机CarpVM:C中有趣的VM,让我们一起来看看这个。MicroPython :旨在实现单片机上Python3.x的实现TinyVM:用纯粹的ANSI C编写的小型,快速,轻量级的虚拟机。Web应用框架Civetweb :提供易于使用,强大的,C/C++嵌入式Web服务器,带有可选的CGI,SSL和Lua支持。CppCMS :免费高性能的Web开发框架(不是 CMS).Crow :一个C++微型web框架(灵感来自于Python Flask)Kore :使用C语言开发的用于web应用程序的超快速和灵活的web服务器/框架。libOnion:轻量级的库,帮助你使用C编程语言创建web服务器。QDjango:使用C++编写的,基于Qt库的web框架,试图效仿Django API,因此得此名。Wt :开发Web应用的C++库。XMLXML就是个垃圾,xml的解析很烦人,对于计算机它也是个灾难。这种糟糕的东西完全没有存在的理由了。-Linus TorvaldsExpat :用C语言编写的xml解析库Libxml2 :Gnome的xml C解析器和工具包libxml++ :C++的xml解析器PugiXML :用于C++的,支持XPath的轻量级,简单快速的XML解析器。RapidXml :试图创建最快速的XML解析器,同时保持易用性,可移植性和合理的W3C兼容性。TinyXML :简单小型的C++XML解析器,可以很容易地集成到其它项目中。TinyXML2:简单快速的C++CML解析器,可以很容易集成到其它项目中。TinyXML++:TinyXML的一个全新的接口,使用了C++的许多许多优势,模板,异常和更好的异常处理。Xerces-C++ :用可移植的C++的子集编写的XML验证解析器。qxmledit:基于Qt的XML编辑软件。多项混杂一些有用的库或者工具,但是不适合上面的分类,或者还没有分类。C++ Format :C++的小型,安全和快速格式化库casacore :从aips++ 派生的一系列C++核心库cxx-prettyprint:用于C++容器的打印库DynaPDF :易于使用的PDF生成库gcc-poison :帮助开发人员禁止应用程序中的不安全的C/C++函数的简单的头文件。googlemock:编写和使用C++模拟类的库HTTP Parser :C的http请求/响应解析器libcpuid :用于x86 CPU检测盒特征提取的小型C库libevil :许可证管理器libusb:允许移动访问USB设备的通用USB库PCRE:正则表达式C库,灵感来自于Perl中正则表达式的功能。Remote Call Framework :C++的进程间通信框架。Scintilla :开源的代码编辑控件Serial Communication Library :C++语言编写的跨平台,串口库。SDS:C的简单动态字符串库SLDR :超轻的DNS解析器SLRE: 超轻的正则表达式库Stage :移动机器人模拟器VarTypes:C++/Qt4功能丰富,面向对象的管理变量的框架。ZBar:‘条形码扫描器’库,可以扫描照片,图片和视频流中的条形码,并返回结果。CppVerbalExpressions :易于使用的C++正则表达式QtVerbalExpressions:基于C++ VerbalExpressions 库的Qt库PHP-CPP:使用C++来构建PHP扩展的库Better String :C的另一个字符串库,功能更丰富,但是没有缓冲溢出问题,还包含了一个C++包装器。软件用于创建开发环境的软件编译器C/C++编译器列表Clang :由苹果公司开发的GCC:GNU编译器集合Intel C++ Compiler :由英特尔公司开发LLVM :模块化和可重用编译器和工具链技术的集合Microsoft Visual C++ :MSVC,由微软公司开发Open WatCom :Watcom,C,C++和Fortran交叉编译器和工具TCC :轻量级的C语言编译器在线编译器在线C/C++编译器列表codepad :在线编译器/解释器,一个简单的协作工具CodeTwist:一个简单的在线编译器/解释器,你可以粘贴的C,C++或者Java代码,在线执行并查看结果coliru :在线编译器/shell, 支持各种C++编译器Compiler Explorer:交互式编译器,可以进行汇编输出CompileOnline:Linux上在线编译和执行C++程序Ideone :一个在线编译器和调试工具,允许你在线编译源代码并执行,支持60多种编程语言。调试器C/C++调试器列表Comparison of debuggers :来自维基百科的调试器列表GDB :GNU调试器Valgrind:内存调试,内存泄露检测,性能分析工具。集成开发环境(IDE)C/C++集成开发环境列表AppCode :构建与JetBrains’ IntelliJ IDEA 平台上的用于Objective-C,C,C++,Java和Java开发的集成开发环境CLion:来自JetBrains的跨平台的C/C++的集成开发环境Code::Blocks :免费C,C++和Fortran的集成开发环境CodeLite :另一个跨平台的免费的C/C++集成开发环境Dev-C++:可移植的C/C++/C++11集成开发环境Eclipse CDT:基于Eclipse平台的功能齐全的C和C++集成开发环境Geany :轻量级的快速,跨平台的集成开发环境。IBM VisualAge :来自IBM的家庭计算机集成开发环境。Irony-mode:由libclang驱动的用于Emacs的C/C++微模式KDevelop:免费开源集成开发环境Microsoft Visual Studio :来自微软的集成开发环境NetBeans :主要用于Java开发的的集成开发环境,也支持其他语言,尤其是PHP,C/C++和HTML5。Qt Creator:跨平台的C++,Javascript和QML集成开发环境,也是Qt SDK的一部分。rtags:C/C++的客户端服务器索引,用于 跟基于clang的emacs的集成Xcode :由苹果公司开发YouCompleteMe:一个用于Vim的根据你敲的代码快速模糊搜索并进行代码补全的引擎。构建系统Bear :用于为clang工具生成编译数据库的工具Biicode:基于文件的简单依赖管理器。CMake :跨平台的免费开源软件用于管理软件使用独立编译的方法进行构建的过程。CPM:基于CMake和Git的C++包管理器FASTBuild:高性能,开源的构建系统,支持高度可扩展性的编译,缓冲和网络分布。Ninja :专注于速度的小型构建系统Scons :使用Python scipt 配置的软件构建工具tundra :高性能的代码构建系统,甚至对于非常大型的软件项目,也能提供最好的增量构建次数。tup:基于文件的构建系统,用于后台监控变化的文件。静态代码分析提高质量,减少瑕疵的代码分析工具列表Cppcheck :静态C/C++代码分析工具include-what-you-use :使用clang进行代码分析的工具,可以#include在C和C++文件中。OCLint :用于C,C++和Objective-C的静态源代码分析工具,用于提高质量,减少瑕疵。Clang Static Analyzer:查找C,C++和Objective-C程序bug的源代码分析工具List of tools for static code analysis :来自维基百科的静态代码分析工具列表内容来源于CSDN博主小麦大叔看完这篇内容后,相信以下三件事,也会给你带来帮助:1、点赞,让更多小伙伴能看到这篇内容,你的点赞是我持续创作的动力2、提升自己,CSDN放出了大量免费课送给正在阅读的你,包含Python、Java、人工智能、算法、机器学习等热门领域,只要你想学,这里都有!戳下方链接查看:https://edu.csdn.net/course/index?is_member=1&is_free=2?utm_source=eduxy_zhihuyl_mfk_06083、关注【程序员知识圈】,更多面试题、面试技巧等优质内容等你来撩!编辑于 2020-06-08 14:51​赞同 873​​21 条评论​分享​收藏​喜欢收起​1412​开源框架Workflow/srpc开发者♥架构鶸一只​ 关注Workflow就特别适合用来学习网络编程。开源一年多,最近刚被Debian Linux纳入自带安装包。其实能够通过 apt-get install 安装的网络框架真的屈指可数,最近几年或者说国内几乎是没有的,因此看得出是对Workflow的通用性和轻便性的一种认可~ (๑╹ヮ╹๑)ノhttps://packages.debian.org/sid/libworkflow1而这两点也恰恰是Workflow适合用来学习网络编程的地方:1. 轻量级——适合学习源码Workflow底层无依赖,网络都是自己调用 epoll / kqueue / iocp,并且在之上封装出企业级的高并发网络模块。作为C++网络框架,Workflow对C++的功能使用非常克制,很少见到难以理解的用法或者繁杂的语法,项目源码小而美,非常值得学习。2. 易用性——容易产出项目由于接口简单,且包括了许多常用网络协议:Http、Redis、MySQL、Kafka、Websocket、DNS,因此基于Workflow很容易实现出一个自己的项目。在项目主页的tutorial目录下,有若干现成的示例,包括wget、http_proxy、http_file_server等趁手的小工具,执行make即可直接编译出来,方便使用+魔改~除了以上两点之外,还有以下特点也值得分享给正在学习工业级项目的小伙伴:3. 用任务流解决异步大难题网络编程难在哪里呢?我个人认为如果要保证高性能,绕不开的难题就是异步机制。针对这个问题,Workflow创新性地使用任务来组织异步网络资源:对client来说,每一次请求都是发起一个任务,在回调函数callback中,我们可以拿到对方回复的内容;对server来说,每一次处理都是被发起一个任务,在执行函数process中,我们可以填要给对方回复的内容;而任务可以通过串行(SeriesWork)和并行(ParallelWork)组装起来,解决异步编程时业务逻辑零碎的问题。4. 通信与计算的对称性我们见到的网络库、RPC框架有很多,但是我们知道工业级使用上往往需要面临网络和计算混杂的情况,这就是Workflow能够比许多网络框架显得更通用的地方:计算通信融为一体。在Workflow中,一切都是对称的:通信使用的,是网络;计算使用的,是CPU(也可以是GPU)。通信调度的系统资源,是fd;计算调度的系统资源,是thread。通信过程是:协议 + 请求 + 回复;计算过程是:算法 + 输入 + 输出。这不仅在项目架构上显得非常清晰精巧,而且在开发者使用上心智负担也会小很多。而无论是通信还是计算,他们最终展现给开发者的形式都是一个任务,因此他们可以同等地被组装起来,做我们需要的业务逻辑。最后附上Github项目地址,欢迎小伙伴们围观尝试~~~编辑于 2022-01-05 15:25​赞同 141​​18 条评论​分享​收藏​喜欢

C语言之网络编程(服务器和客户端)_c语言服务器编程-CSDN博客

>

C语言之网络编程(服务器和客户端)_c语言服务器编程-CSDN博客

C语言之网络编程(服务器和客户端)

最新推荐文章于 2024-01-21 21:37:39 发布

镜花寒

最新推荐文章于 2024-01-21 21:37:39 发布

阅读量6.4w

收藏

522

点赞数

83

文章标签:

网络编程

C语言

linux编程

服务器和客户端

多并发服务器

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

本文链接:https://blog.csdn.net/zh0314/article/details/77387162

版权

Linux网络编程

1、 套接字:源IP地址和目的IP地址以及源端口号和目的端口号的组合称为套接字。其用于标识客户端请求的服务器和服务。

常用的TCP/IP协议的3种套接字类型如下所示。

(1)流套接字(SOCK_STREAM):

流套接字用于提供面向连接、可靠的数据传输服务。该服务将保证数据能够实现无差错、无重复发送,并按顺序接收。流套接字之所以能够实现可靠的数据服务,原因在于其使用了传输控制协议,即TCP(The Transmission ControlProtocol)协议。

(2)       数据报套接字(SOCK_DGRAM):

数据报套接字提供了一种无连接的服务。该服务并不能保证数据传输的可靠性,数据有可能在传输过程中丢失或出现数据重复,且无法保证顺序地接收到数据。数据报套接字使用UDP(User Datagram Protocol)协议进行数据的传输。由于数据报套接字不能保证数据传输的可靠性,对于有可能出现的数据丢失情况,需要在程序中做相应的处理。

(3)       原始套接字(SOCK_RAW):(一般不用这个套接字)

原始套接字(SOCKET_RAW)允许对较低层次的协议直接访问,比如IP、 ICMP协议,它常用于检验新的协议实现,或者访问现有服务中配置的新设备,因为RAW SOCKET可以自如地控制Windows下的多种协议,能够对网络底层的传输机制进行控制,所以可以应用原始套接字来操纵网络层和传输层应用。比如,我们可以通过RAW SOCKET来接收发向本机的ICMP、IGMP协议包,或者接收TCP/IP栈不能够处理的IP包,也可以用来发送一些自定包头或自定协议的IP包。网络监听技术很大程度上依赖于SOCKET_RAW

2、 套接字基本函数:

(1)      创建套接字:int socket(int family, int type, intprotocol);

功能介绍:

      在Linux操作系统中,一切皆文件,这个大家都知道,个人理解创建socket的过程其实就是一个获得文件描述符的过程,当然这个过程会是比较复杂的。可以从内核中找到创建socket的代码,并且socket的创建和其他的listen,bind等操作分离开来。socket函数完成正确的操作是返回值大于0的文件描述符,当返回小于0的值时,操作错误。同样是返回一个文件描述符,但是会因为三个参数组合不同,对于数据具体的工作流程不同,对于应用层编程来说,这些也是不可见的。

参数说明:

      从socket创建的函数可以看出,socket有三个参数,family代表一个协议族,比较熟知的就是AF_INET,PF_PACKET等;第二个参数是协议类型,常见类型是SOCK_STREAM,SOCK_DGRAM, SOCK_RAW, SOCK_PACKET等;第三个参数是具体的协议,对于标准套接字来说,其值是0,对于原始套接字来说就是具体的协议值。

(2)      套接字绑定函数: intbind(int sockfd, const struct sockaddr *myaddr, socklen_t addrlen);

功能介绍:

      bind函数主要应用于服务器模式一端,其主要的功能是将addrlen长度 structsockaddr类型的myaddr地址与sockfd文件描述符绑定到一起,在sockaddr中主要包含服务器端的协议族类型,网络地址和端口号等。在客户端模式中不需要使用bind函数。当bind函数返回0时,为正确绑定,返回-1,则为绑定失败。

参数说明:

      bind函数的第一个参数sockfd是在创建socket套接字时返回的文件描述符。

      bind函数的第二个参数是structsockaddr类型的数据结构,由于structsockaddr数据结构类型不方便设置,所以通常会通过对tructsockaddr_in进行地质结构设置,然后进行强制类型转换成structsockaddr类型的数据,

 

(3)      监听函数:int listen(int sockfd, int backlog);

功能介绍:

      刚开始理解listen函数会有一个误区,就是认为其操作是在等在一个新的connect的到来,其实不是这样的,真正等待connect的是accept操作,listen的操作就是当有较多的client发起connect时,server端不能及时的处理已经建立的连接,这时就会将connect连接放在等待队列中缓存起来。这个等待队列的长度有listen中的backlog参数来设定。listen和accept函数是服务器模式特有的函数,客户端不需要这个函数。当listen运行成功时,返回0;运行失败时,返回值位-1.

参数说明:

      sockfd是前面socket创建的文件描述符;backlog是指server端可以缓存连接的最大个数,也就是等待队列的长度。

 

(4)      请求接收函数: int accept(int sockfd, structsockaddr *client_addr, socklen_t *len);

功能介绍:

      接受函数accept其实并不是真正的接受,而是客户端向服务器端监听端口发起的连接。对于TCP来说,accept从阻塞状态返回的时候,已经完成了三次握手的操作。Accept其实是取了一个已经处于connected状态的连接,然后把对方的协议族,网络地址以及端口都存在了client_addr中,返回一个用于操作的新的文件描述符,该文件描述符表示客户端与服务器端的连接,通过对该文件描述符操作,可以向client端发送和接收数据。同时之前socket创建的sockfd,则继续监听有没有新的连接到达本地端口。返回大于0的文件描述符则表示accept成功,否则失败。

参数说明:

      sockfd是socket创建的文件描述符;client_addr是本地服务器端的一个structsockaddr类型的变量,用于存放新连接的协议族,网络地址以及端口号等;第三个参数len是第二个参数所指内容的长度,对于TCP来说其值可以用sizeof(structsockaddr_in)来计算大小,说要说明的是accept的第三个参数要是指针的形式,因为这个值是要传给协议栈使用的。

(5)客户端请求连接函数: intconnect(int sock_fd, struct sockaddr *serv_addr,int addrlen);

功能介绍:

      连接函数connect是属于client端的操作函数,其目的是向服务器端发送连接请求,这也是从客户端发起TCP三次握手请求的开始,服务器端的协议族,网络地址以及端口都会填充到connect函数的serv_addr地址当中。当connect返回0时说明已经connect成功,返回值是-1时,表示connect失败。

参数说明:

      connect的第一个参数是socket创建的文件描述符;第二个参数是一个structsockaddr类型的指针,这个参数中设置的是要连接的目标服务器的协议族,网络地址以及端口号;第三个参数表示第二个参数内容的大小,与accept不同,这个值不是一个指针。

      

      在服务器端和客户端建立连接之后是进行数据间的发送和接收,主要使用的接收函数是recv和read,发送函数是send和write。因为对于socket套接字来说,最终实际操作的是文件描述符,所以可以使用对文件进行操作的接收和发送函数对socket套接字进行操作。read和write函数是文件编程里的知识,所以这里不再做多与的赘述。

 

3、 有了以上的知识,那么我们就可以编写一个简单的服务器和客户端了

(1)       简易服务器:这个服务器只能与一个客户端相连接,如果有多个客户端就不能用这个服务器进行连接。

代码:

#include

#include

#include

#include

#include

#include

#define PORT 9990 //端口号

#define SIZE 1024 //定义的数组大小

int Creat_socket() //创建套接字和初始化以及监听函数

{

int listen_socket = socket(AF_INET, SOCK_STREAM, 0); //创建一个负责监听的套接字

if(listen_socket == -1)

{

perror("socket");

return -1;

}

struct sockaddr_in addr;

memset(&addr, 0, sizeof(addr));

addr.sin_family = AF_INET; /* Internet地址族 */

addr.sin_port = htons(PORT); /* 端口号 */

addr.sin_addr.s_addr = htonl(INADDR_ANY); /* IP地址 */

int ret = bind(listen_socket, (struct sockaddr *)&addr, sizeof(addr)); //连接

if(ret == -1)

{

perror("bind");

return -1;

}

ret = listen(listen_socket, 5); //监听

if(ret == -1)

{

perror("listen");

return -1;

}

return listen_socket;

}

int wait_client(int listen_socket)

{

struct sockaddr_in cliaddr;

int addrlen = sizeof(cliaddr);

printf("等待客户端连接。。。。\n");

int client_socket = accept(listen_socket, (struct sockaddr *)&cliaddr, &addrlen); //创建一个和客户端交流的套接字

if(client_socket == -1)

{

perror("accept");

return -1;

}

printf("成功接收到一个客户端:%s\n", inet_ntoa(cliaddr.sin_addr));

return client_socket;

}

void hanld_client(int listen_socket, int client_socket) //信息处理函数,功能是将客户端传过来的小写字母转化为大写字母

{

char buf[SIZE];

while(1)

{

int ret = read(client_socket, buf, SIZE-1);

if(ret == -1)

{

perror("read");

break;

}

if(ret == 0)

{

break;

}

buf[ret] = '\0';

int i;

for(i = 0; i < ret; i++)

{

buf[i] = buf[i] + 'A' - 'a';

}

printf("%s\n", buf);

write(client_socket, buf, ret);

if(strncmp(buf, "end", 3) == 0)

{

break;

}

}

close(client_socket);

}

int main()

{

int listen_socket = Creat_socket();

int client_socket = wait_client(listen_socket);

hanld_client(listen_socket, client_socket);

close(listen_socket);

return 0;

}

(2) 多进程并发服务器:该服务器就完全弥补了上一个服务器的不足,可以同时处理多个客户端,只要有客户端来连接它,他就能响应。在我们这个服务器中,父进程主要负责监听,所以在父进程一开始就要把父进程的接收函数关闭掉,防止父进程在接收函数处阻塞,导致子进程不能创建成功。同理,子进程主要负责接收客户端,并做相关处理,所以子进程在一创建就要把监听函数关闭,不然会导致服务器功能的紊乱。这个服务器有一个特别要注意的是,子进程在退出时会产生僵尸进程,所以我们一定要对子进程退出后进行处理。

代码:

#include

#include

#include

#include

#include

#include

#include

#include

#define PORT 9990

#define SIZE 1024

int Creat_socket() //创建套接字和初始化以及监听函数

{

int listen_socket = socket(AF_INET, SOCK_STREAM, 0); //创建一个负责监听的套接字

if(listen_socket == -1)

{

perror("socket");

return -1;

}

struct sockaddr_in addr;

memset(&addr, 0, sizeof(addr));

addr.sin_family = AF_INET; /* Internet地址族 */

addr.sin_port = htons(PORT); /* 端口号 */

addr.sin_addr.s_addr = htonl(INADDR_ANY); /* IP地址 */

int ret = bind(listen_socket, (struct sockaddr *)&addr, sizeof(addr)); //连接

if(ret == -1)

{

perror("bind");

return -1;

}

ret = listen(listen_socket, 5); //监听

if(ret == -1)

{

perror("listen");

return -1;

}

return listen_socket;

}

int wait_client(int listen_socket)

{

struct sockaddr_in cliaddr;

int addrlen = sizeof(cliaddr);

printf("等待客户端连接。。。。\n");

int client_socket = accept(listen_socket, (struct sockaddr *)&cliaddr, &addrlen); //创建一个和客户端交流的套接字

if(client_socket == -1)

{

perror("accept");

return -1;

}

printf("成功接收到一个客户端:%s\n", inet_ntoa(cliaddr.sin_addr));

return client_socket;

}

void hanld_client(int listen_socket, int client_socket) //信息处理函数,功能是将客户端传过来的小写字母转化为大写字母

{

char buf[SIZE];

while(1)

{

int ret = read(client_socket, buf, SIZE-1);

if(ret == -1)

{

perror("read");

break;

}

if(ret == 0)

{

break;

}

buf[ret] = '\0';

int i;

for(i = 0; i < ret; i++)

{

buf[i] = buf[i] + 'A' - 'a';

}

printf("%s\n", buf);

write(client_socket, buf, ret);

if(strncmp(buf, "end", 3) == 0)

{

break;

}

}

close(client_socket);

}

void handler(int sig)

{

while (waitpid(-1, NULL, WNOHANG) > 0)

{

printf ("成功处理一个子进程的退出\n");

}

}

int main()

{

int listen_socket = Creat_socket();

signal(SIGCHLD, handler); //处理子进程,防止僵尸进程的产生

while(1)

{

int client_socket = wait_client(listen_socket); //多进程服务器,可以创建子进程来处理,父进程负责监听。

int pid = fork();

if(pid == -1)

{

perror("fork");

break;

}

if(pid > 0)

{

close(client_socket);

continue;

}

if(pid == 0)

{

close(listen_socket);

hanld_client(listen_socket, client_socket);

break;

}

}

close(listen_socket);

return 0;

}

(3) 多线程并发服务器:上一个多进程服务器有一个缺点,就是每当一个子进程得到响应的时候,都要复制父进程的一切信息,这样就导致了CPU资源的浪费,当客户端有很多来连接这个服务器的时候,就会产生很多的子进程,会导致服务器的响应变得很慢。所以我们就想到了多线程并发服务器,我们知道线程的速度是进程的30倍左右,所以我们就用线程来做服务器。

代码:

#include

#include

#include

#include

#include

#include

#include

#define PORT 9990

#define SIZE 1024

int Creat_socket() //创建套接字和初始化以及监听函数

{

int listen_socket = socket(AF_INET, SOCK_STREAM, 0); //创建一个负责监听的套接字

if(listen_socket == -1)

{

perror("socket");

return -1;

}

struct sockaddr_in addr;

memset(&addr, 0, sizeof(addr));

addr.sin_family = AF_INET; /* Internet地址族 */

addr.sin_port = htons(PORT); /* 端口号 */

addr.sin_addr.s_addr = htonl(INADDR_ANY); /* IP地址 */

int ret = bind(listen_socket, (struct sockaddr *)&addr, sizeof(addr)); //连接

if(ret == -1)

{

perror("bind");

return -1;

}

ret = listen(listen_socket, 5); //监听

if(ret == -1)

{

perror("listen");

return -1;

}

return listen_socket;

}

int wait_client(int listen_socket)

{

struct sockaddr_in cliaddr;

int addrlen = sizeof(cliaddr);

printf("等待客户端连接。。。。\n");

int client_socket = accept(listen_socket, (struct sockaddr *)&cliaddr, &addrlen); //创建一个和客户端交流的套接字

if(client_socket == -1)

{

perror("accept");

return -1;

}

printf("成功接收到一个客户端:%s\n", inet_ntoa(cliaddr.sin_addr));

return client_socket;

}

void hanld_client(int listen_socket, int client_socket) //信息处理函数,功能是将客户端传过来的小写字母转化为大写字母

{

char buf[SIZE];

while(1)

{

int ret = read(client_socket, buf, SIZE-1);

if(ret == -1)

{

perror("read");

break;

}

if(ret == 0)

{

break;

}

buf[ret] = '\0';

int i;

for(i = 0; i < ret; i++)

{

buf[i] = buf[i] + 'A' - 'a';

}

printf("%s\n", buf);

write(client_socket, buf, ret);

if(strncmp(buf, "end", 3) == 0)

{

break;

}

}

close(client_socket);

}

int main()

{

int listen_socket = Creat_socket();

while(1)

{

int client_socket = wait_client(listen_socket);

pthread_t id;

pthread_create(&id, NULL, hanld_client, (void *)client_socket); //创建一个线程,来处理客户端。

pthread_detach(id); //把线程分离出去。

}

close(listen_socket);

return 0;

}

(4)客户端:客户端相对于服务器来说就简单多了,客户端只需要创建和服务器相连接的套接字,然后对其初始化,然后再进行连接就可以了,连接上服务器就可以发送你想发送的数据了。

代码:

#include

#include

#include

#include

#include

#include

#define PORT 9990

#define SIZE 1024

int main()

{

int client_socket = socket(AF_INET, SOCK_STREAM, 0); //创建和服务器连接套接字

if(client_socket == -1)

{

perror("socket");

return -1;

}

struct sockaddr_in addr;

memset(&addr, 0, sizeof(addr));

addr.sin_family = AF_INET; /* Internet地址族 */

addr.sin_port = htons(PORT); /* 端口号 */

addr.sin_addr.s_addr = htonl(INADDR_ANY); /* IP地址 */

inet_aton("127.0.0.1", &(addr.sin_addr));

int addrlen = sizeof(addr);

int listen_socket = connect(client_socket, (struct sockaddr *)&addr, addrlen); //连接服务器

if(listen_socket == -1)

{

perror("connect");

return -1;

}

printf("成功连接到一个服务器\n");

char buf[SIZE] = {0};

while(1) //向服务器发送数据,并接收服务器转换后的大写字母

{

printf("请输入你相输入的:");

scanf("%s", buf);

write(client_socket, buf, strlen(buf));

int ret = read(client_socket, buf, strlen(buf));

printf("buf = %s", buf);

printf("\n");

if(strncmp(buf, "END", 3) == 0) //当输入END时客户端退出

{

break;

}

}

close(listen_socket);

return 0;

}

优惠劵

镜花寒

关注

关注

83

点赞

522

收藏

觉得还不错?

一键收藏

知道了

9

评论

C语言之网络编程(服务器和客户端)

Linux网络编程1、 套接字:源IP地址和目的IP地址以及源端口号和目的端口号的组合称为套接字。其用于标识客户端请求的服务器和服务。常用的TCP/IP协议的3种套接字类型如下所示。(1)流套接字(SOCK_STREAM):流套接字用于提供面向连接、可靠的数据传输服务。该服务将保证数据能够实现无差错、无重复发送,并按顺序接收。流套接字之所以能够实现可靠的数据服务,原因在于其使用

复制链接

扫一扫

C语言网络编程快速入门

01-11

C语言网络编程快速入门

C语言的学习,一般的方式是:先学C,然后是C++,

最好还要有汇编语言和微机原理基础,然后才是Visual

C++。这样的方式,对学习者来说,要花费很多时间和

精力。而在学校教学中,也就没有时间深入学习Win—

dows编程的实用技术了。

其实,具有了C语言基础后,再有一些基本的C++

类的概念,就可以直接学习Windows C编程了。

【TCP/IP】c语言网络编程简单入门(Linux)

weixin_43972830的博客

12-27

830

在Linux系统中有一句话,一切皆文件,即在Linux系统上,哪怕是一些硬件设备也会被抽象为文件,可读可写...所以socket在Linux系统上也可以理解为文件,你向里面写内容,它会自己发出去,别人给你发内容,你就向socket里面读取就行。一台设备,只要配有网卡,网卡设置了ip,网卡接上网线到另一台设备(如交换机,路由器,pc等),那么就可以通过网络编程来与另一台pc进行交互信息。因为如果系统是大端序,调用htonl不会发生改变,如果是小端序,则会变成大端序。

9 条评论

您还未登录,请先

登录

后发表或查看评论

网络编程(客户端与服务端的连接)

weixin_45901415的博客

01-21

796

要使计算机连成的网络能够互通信息,需要对数据传输速率、传输代码、代码结构、传输控制步骤、出错控制等制定一组标准,这一组共同遵守的通信标准就是网络通信协议,不同的计算机之间必须使用相同的通讯协议才能进行通信。​ 七层模型,也称为OSI(Open System Interconnection)参考模型,是国际标准化组织(ISO)制定的一个用于计算机或通讯系统间互联的标准体系。它是一个七层的、抽象的模型体,不仅包括一系列抽象的术语或概念,也包括具体的协议。

网络编程中如何用C语言实现的一个DNS客户端

08-12

DNS可以帮助我们把域名映射到一个IP地址上,或者查询一个IP地址下有那些域名,使用域名访问一个网站或者服务器是一件很平常的事情,很少有人关心域名变成IP地址的实际过程,本文将使用C语言实现一个基本的DNS解析器,通过与DNS服务器的通信完成将一个域名转换成IP地址的过程,本文将提供完整的源程序;阅读本文需要有一定的网络编程基础,熟悉基本的socket编程并对DNS有一些了解,本文对网络编程的初学者难度较大。

在日常的网络活动中,有时会遇到DNS污染的困扰,比如在浏览器中输入域名,却无法到达我们期望到达的网站,这有时就是因为我们收到的DNS回应并不是来自一个合法的DNS服务器;当遇到此类问题时,本文的程序可以帮助你判断是否存在DNS污染。

如果一个网站没有完成备案,则使用域名访问时也无法到达该网站,这其实也是在DNS上做的文章。

C语言实现一个简单的服务器

热门推荐

So Much to Learn

07-04

1万+

C/S结构流程图服务端socket函数为了执行网络I/O,一个进程必须做的第一件事情就是创建一个socket函数/* family 表示协议族 AF_INET(IPv4协议)、AF_INET6(IPv6协议)、AF_LOCAL(Unix域协议)、AF_ROUTE(路由套接字)、AF_KEY( 密钥套接字)

type 表示套接字类型 SOCK_STREAM(字节流套接字)、SOCK

如何用C语言自建一个服务器

JJ_DanTaZhu的博客

11-13

951

利用C语言自建服务器

如何用C语言写一个服务器和客户端(TCP)

wrnmbnmsl的博客

08-11

2885

tcp服务器和客户端

C语言网络编程

Engima_lcm的博客

11-15

2253

网络编程模板代码及TCP/UDP网络协议

[linux] C语言Linux系统编程-TCP通信的11种状态

程序员老狼专注开发aigc或客服系统应用

01-17

502

三次握手由client主动发出SYN请求, 此时client处于SYN_SENT状态(第一次握手)当server收到之后会由LISTEN转变为SYN_REVD状态, 并回复client, client收到应答后处于ESTABLISHED状态, 这个状态就表示client已经准备好通信了(第二次握手)client收到二次握手应答后回复server, server收到应答之后也处于EST...

一个简单的使用C语言实现的TCP客户端和服务器端,可以进行双向通信

逆风水手的博客

04-03

1099

【代码】一个简单的使用C语言实现的TCP客户端和服务器端,可以进行双向通信。

笔记 C socket 实现简单的套接字编程(客户端和客户端连接)

yong1585855343的博客

01-13

1799

0. 套接字

网上很多说套接字名称包括:

IP:port

在 《Windows Socket 网络编程》 Bob Quinn 著的一书中,套接字名称包括:

1. IP

2. port

3. protocol (协议)

1. 图示流程

说明:刚学习 windows socket 编程,能搞懂图中的函数怎么用及其参数的意义算是入门了。

2. 库

#include

#include

#

纯C语言实现DNS服务端与客户端程序

08-13

纯C语言实现DNS服务器与客户端程序,包含客户端与服务端。客户端程序可以请求本地服务端,也可请求公共DNS服务器,支持解析服务端返回的多回答报文。

使用C语言实现服务器/客户端的TCP通信

03-29

本文力求使用简单的描述说明一个服务器/客户端TCP通信的基本程序框架,文中给出了服务器端和客户端的实例源程序,本文适合初学者阅读;本文的程序在ubuntu 20.04中编译运行成功,gcc版本号为:9.4.0

使用C语言实现服务器/客户端的UDP通信

03-29

本文旨在使用简单的例子说明编写一个服务器/客户端模式的UDP通信程序的步骤,并通过一个实例给出了程序的基本框架,本文适合初学者阅读;本文的程序在ubuntu 20.04中编译运行成功,gcc版本号为:9.4.0

C语言网络通信编程(两个客户端两个服务器).zip

05-29

C语言网络通信编程(两个客户端两个服务器)源码

ASP源码基于web的实验室管理系统(自动排课功能的实现)

03-09

ASP源码基于web的实验室管理系统(自动排课功能的实现)本资源系百度网盘分享地址

html+css+bootstrap-家具网站模板下载,沙发家具商城模板Furni.zip

最新发布

03-09

【技术分析】

HTML,是一种制作万维网页面的标准语言,它消除了不同计算机之间信息交流的障碍;

CSS,可以帮助把网页外观做得更加美观;

JavaScript,是一种轻量级的解释型编程语言;

jQuery,使用户能更方便地处理HTML documents、events、实现动画效果,并且方便地为网站提供AJAX交互;

Bootstrap 是快速开发 Web 应用程序的前端工具包。它是一个 CSS,HTML 和 JS 的集合,它使用了最新的浏览器技术,给你的 Web 开发提供了时尚的版式;

AJAX,创建交互式网页应用的网页开发技术。

【设计思路】

用户友好性:界面简洁直观,易于操作,减少用户的学习成本。

模块化设计:将系统功能模块化,每个模块负责一类功能,方便扩展和维护。

Responsiveness:后台管理系统应当是响应式设计,能够适配不同设备屏幕大小,包括电脑、平板和手机等。

权限控制:根据用户角色设定不同的权限,确保用户只能访问其权限范围内的功能。

数据安全:对用户数据进行加密存储、访问控制等措施,保护用户隐私和系统安全。

日志功能:记录关键操作日志,保留操作痕迹。

pandaSDMX-1.7.0-py3-none-any.whl

03-09

Python库是一组预先编写的代码模块,旨在帮助开发者实现特定的编程任务,无需从零开始编写代码。这些库可以包括各种功能,如数学运算、文件操作、数据分析和网络编程等。Python社区提供了大量的第三方库,如NumPy、Pandas和Requests,极大地丰富了Python的应用领域,从数据科学到Web开发。Python库的丰富性是Python成为最受欢迎的编程语言之一的关键原因之一。这些库不仅为初学者提供了快速入门的途径,而且为经验丰富的开发者提供了强大的工具,以高效率、高质量地完成复杂任务。例如,Matplotlib和Seaborn库在数据可视化领域内非常受欢迎,它们提供了广泛的工具和技术,可以创建高度定制化的图表和图形,帮助数据科学家和分析师在数据探索和结果展示中更有效地传达信息。

pandaSDMX-1.0.1-py3-none-any.whl

03-09

Python库是一组预先编写的代码模块,旨在帮助开发者实现特定的编程任务,无需从零开始编写代码。这些库可以包括各种功能,如数学运算、文件操作、数据分析和网络编程等。Python社区提供了大量的第三方库,如NumPy、Pandas和Requests,极大地丰富了Python的应用领域,从数据科学到Web开发。Python库的丰富性是Python成为最受欢迎的编程语言之一的关键原因之一。这些库不仅为初学者提供了快速入门的途径,而且为经验丰富的开发者提供了强大的工具,以高效率、高质量地完成复杂任务。例如,Matplotlib和Seaborn库在数据可视化领域内非常受欢迎,它们提供了广泛的工具和技术,可以创建高度定制化的图表和图形,帮助数据科学家和分析师在数据探索和结果展示中更有效地传达信息。

用C语言tcp网络编程编译用客户端下载文件

05-26

以下是基于C语言的TCP网络编程示例代码,用于从服务器下载文件: ```c #include #include #include #include #include #include #define BUFFER_SIZE 1024 int main(int argc, char *argv[]) { if (argc !...

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

非常没帮助

没帮助

一般

有帮助

非常有帮助

提交

镜花寒

CSDN认证博客专家

CSDN认证企业博客

码龄7年

暂无认证

43

原创

17万+

周排名

116万+

总排名

18万+

访问

等级

1683

积分

120

粉丝

192

获赞

26

评论

669

收藏

私信

关注

热门文章

C语言之网络编程(服务器和客户端)

64619

关于C语言中“x++”和“++x”的问题

19211

C语言之生产者与消费者模型

16961

C语言基础编程(switch语句)

16642

C语言编程之递归求阶乘

9207

最新评论

C语言之生产者与消费者模型

s1nd:

代码风格很棒,不过num作为生产编号的话,消费者不应该修改它

C语言编程之递归求阶乘

Ş৳ʀɨꪜꫀ828:

n等1时候,不应该返回1吗

C语言之生产者与消费者模型

a3066886794:

会生产同样序号

C语言之生产者与消费者模型

a3066886794:

没有包含scanf和usleep的头文件

关于C语言中“x++”和“++x”的问题

提克迪奥斯:

太牛啦

您愿意向朋友推荐“博客详情页”吗?

强烈不推荐

不推荐

一般般

推荐

强烈推荐

提交

最新文章

聊天室(c/s架构)

c++多继承

c++之运算符重载基础

2017年43篇

目录

目录

最新文章

聊天室(c/s架构)

c++多继承

c++之运算符重载基础

2017年43篇

目录

评论 9

被折叠的  条评论

为什么被折叠?

到【灌水乐园】发言

查看更多评论

添加红包

祝福语

请填写红包祝福语或标题

红包数量

红包个数最小为10个

红包总金额

红包金额最低5元

余额支付

当前余额3.43元

前往充值 >

需支付:10.00元

取消

确定

下一步

知道了

成就一亿技术人!

领取后你会自动成为博主和红包主的粉丝

规则

hope_wisdom 发出的红包

实付元

使用余额支付

点击重新获取

扫码支付

钱包余额

0

抵扣说明:

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

余额充值

C,C++网络编程学习指南_c语言的网络编程和c++-CSDN博客

>

C,C++网络编程学习指南_c语言的网络编程和c++-CSDN博客

C,C++网络编程学习指南

最新推荐文章于 2024-03-05 23:05:38 发布

m0_67392661

最新推荐文章于 2024-03-05 23:05:38 发布

阅读量138

收藏

2

点赞数

分类专栏:

java

文章标签:

java

后端

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

本文链接:https://blog.csdn.net/m0_67392661/article/details/124505376

版权

java

专栏收录该内容

273 篇文章

5 订阅

订阅专栏

1. 扎实的C,C++基础知识 参考资料《C程序设计》,《C++ primer》。

2. TCP/IP协议 经典书是:W.Richard Stevens 著《TCP/IP详解》三卷书,卷1是协议,卷2是实现,卷3是TCP事务协议等。还有官方的协议文档:RFC 当然也可以在网上下载电子书。 经典的开源协议分析工具:Wireshark. 简单的开源TCP/IP协议栈:LwIP,或者Linux 1.0里包含的协议栈,当然也可以看看FreeBSD的TCP/IP协议栈。 ** 3. 实际指导网络编程的书** Winodws平台,经典书是《windows网络编程》第二版。 Linux平台,经典书是W.Richard Stevens 著《UNIX网络编程》。

4. VC++开发 侯捷著 《深入浅出MFC》, 《windows程序设计》,《Windows核心编程》,Microsoft的MSDN。

大家有什么好的资源,电子书,可以贴上来。有关网络编程的学习经验,心得,技巧等等,和大家一起分享。我会持续编辑添加到本楼!

1. Linux TCP/IP 协议栈分析,这是chinaunix.net论坛里的N人写的电子书,可以在这里下载PDF版本。 http://blog.chinaunix.net/u2/85263/showart_1810785.html

2. 《TCP/IP详解》三卷书,PDF版本下载地址: 《TCP/IP详解,卷1:协议》, http://www.laogu.com/ds_510.htm 《TCP/IP详解,卷2:实现》, http://www.laogu.com/ds_511.htm 《TCP/IP详解,卷3:tcp事务协议等》, http://www.laogu.com/ds_512.htm

3. Wireshark 开源的经典的协议分析工具Wireshark, http://www.wireshark.org/

4. Winpcap( linux version: libpcap) and WinDump: tcpdump for Windows http://www.winpcap.org/

5. Minix的作者,著的《计算机网络》也很经典,建议看看,这本书是很多大学的计算机专业教材。 http://product.dangdang.com/product.aspx?product_id=20446391

6. RFC官方网站的RFC文档索引: http://www.ietf.org/download/rfc-index.txt

网络编程书籍补充以下

C++网络编程 卷1 运用ACE和模式消除复杂性 C++网络编程 卷2 基于ACE和框架的系统化复用 ACE自适配通信环境中文技术文档

Visual+C++网络高级编程 Windows网络与通信程序设计 精通Windows+Sockets网络开发——基于Visual+C++实现

开源网络封装库 ACE,ICE,asio,cppsocket,netclass,poco,SimpleSocket,socketman,Sockets 开源下载工具 fdm, eMulePlus,eMule 开源FTP FileZilla 开源服务器 Apache 网游服务器开源框架 GNE,HawkNL,RakNet,SDL_net

最好能参加实际的网络项目,这样能见识更多成熟的网络类库

平常使用的工具 Ethereal -------协议分析 SockMon5 -------抓包及错误分析

关注博主即可阅读全文

优惠劵

m0_67392661

关注

关注

0

点赞

2

收藏

觉得还不错?

一键收藏

知道了

0

评论

C,C++网络编程学习指南

1. 扎实的C,C++基础知识参考资料《C程序设计》,《C++ primer》。2. TCP/IP协议经典书是:W.Richard Stevens 著《TCP/IP详解》三卷书,卷1是协议,卷2是实现,卷3是TCP事务协议等。还有官方的协议文档:RFC当然也可以在网上下载电子书。经典的开源协议分析工具:Wireshark.简单的开源TCP/IP协议栈:LwIP,或者Linux 1.0里包含的协议栈,当然也可以看看FreeBSD的TCP/IP协议栈。**3. 实际指导网络编程的书**Wino

复制链接

扫一扫

专栏目录

c++网络编程实例.pdf

09-30

c++网络编程实例.pdf

Windows网络编程.pdf

09-30

Windows网络编程.pdf

参与评论

您还未登录,请先

登录

后发表或查看评论

高质量c/c++编程指南

11-08

培养良好的编程代码风格

Windows网络编程 杨秋黎 课后习题答案.pdf

07-04

Windows网络编程(第2版)杨秋黎 课后习题答案

VC++网络编程-郑阿奇.zip.001

08-13

VC++网络编程-郑阿奇.zip.001 有实例源码 课程PPT

C++ 网络编程学习指南

lanhaics的专栏

03-19

2623

C,C++网络编程学习简明指南

1. 扎实的C,C++基础知识

参考资料《C程序设计》,《C++ primer》。

2. TCP/IP协议

经典书是:W.Richard Stevens 著《TCP/IP详解》三卷书,卷1是协议,卷2是实现,卷3是TCP事务协议等。还有官方的协议文档:RFC

当然也可以在网上下载电子书。

经典的开源协议分析工具:Wireshark.

简单的

c语言网络编程实例pdf下载,《C语言网络编程快速入门.pdf》-支持高清全文免费浏览-max文档...

weixin_39962889的博客

05-18

354

WindowsC语言网络编程快速入门_..撰文 /魏云华C语言的学习,一般的方式是:先学C,然后是C++, WindowsC程序最好还要有汇编语言和微机原理基础,然后才是Visualm:lud r'da_IS.bC++。这样的方式,对学习者来说,要花费很多时间和 APTENTRY w{nMain(HINSTANCE hznstance。HINSTANCE咿re ...

WindowsSocket网络编程.pdf

10-02

WindowsSocket网络编程.pdf

Visual C++网络编程教程(Visual Studio 2010平台)郑阿奇

12-28

Visual C++网络编程教程(Visual Studio 2010平台)郑阿奇 pdf文档

高质量c++c编程指南_c++编程_

09-29

高质量C++编程指导,将对c++初学者进阶有很大帮助

高质量C/C++编程指南

04-27

高质量C/C++编程指南

Windows Socket2网络编程技术PDF+源码

11-08

Windows Socket2网络编程技术PDF+源码

高质量c++c编程指南.docx

11-16

高质量c++c编程指南.docx

Windows系统编程 原书第4版pdf

02-28

该书主要是利用windows API进行应用程序开发,有文件系统、进程和线程管理、进程间通信、网络编程以及同步等核心系统服务。

Java集合5-HashSet

最新发布

wujianyouhun的专栏

03-05

544

HashSet的原理比较简单,几乎全部借助于HashMap来实现的。由于 HashSet 的底层是基于 HashMap 实现的,因此具有 HashMap 的特性,如高效的添加、查找操作(平均情况下为 O(1)),去重功能等。不过需要注意的是,HashSet 并不保证元素的顺序,元素存储的顺序与插入顺序可能不同,因为它是根据哈希值存储的。所以HashMap会出现的问题HashSet依然不能避免。

c/c++安全编程指南

04-19

C/C++安全编程指南是一本关于如何编写安全的C/C++代码的书。其主要目的是帮助程序员避免常见的安全漏洞和攻击,例如缓冲区溢出和代码注入等。该书介绍了许多编程技术和实践,包括动态内存分配、字符数组处理和输入...

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

非常没帮助

没帮助

一般

有帮助

非常有帮助

提交

普通网友

CSDN认证博客专家

CSDN认证企业博客

码龄2年

暂无认证

374

原创

-

周排名

-

总排名

56万+

访问

等级

4233

积分

2万+

粉丝

240

获赞

98

评论

1371

收藏

私信

关注

热门文章

vue-cli(vue脚手架)安装 详细教程

38176

html爱心表白代码(最全)

36542

linux查看进程号、端口号

22446

mysql数据库密码设置的六种方法

17584

Docker 自动启动和容器自动启动

14264

分类专栏

学习路线

67篇

阿里巴巴

68篇

面试

68篇

java

273篇

前端

36篇

html

36篇

后端

13篇

最新评论

linux虚拟机搭建后找不到ifconfig命令

2401_83434833:

验证了,感谢

覆盖 Safari、Edge,主流浏览器几乎均已实现 WebGL 2.0 支持

清蒸鱼跃龙门:

将 Chrome 切换为使用 ANGLE 的 Metal 后端,这是什么意思?

解决 Docker Desktop for Mac 下载镜像缓慢的问题

2301_81479319:

总是显示在122字符有空格 但一直消不掉

nodejs切换版本使用(不需要卸载重装)

m0_63656340:

这个执行命令的语句是不是不全啊

java.lang.NoSuchMethodError 原因和处理方案

米达麦呀:

可以用 mvn dependency:analyze,mvn dependency:tree 命令辅助分析加载包的顺序。 不明白啊

您愿意向朋友推荐“博客详情页”吗?

强烈不推荐

不推荐

一般般

推荐

强烈推荐

提交

最新文章

web crawler 抓某前程的小小tips(低调发育)

mysql:列类型之float、double

hive中判断一个字符串是否包含另一个子串的四种方法,sql中也可用

2022年377篇

目录

目录

分类专栏

学习路线

67篇

阿里巴巴

68篇

面试

68篇

java

273篇

前端

36篇

html

36篇

后端

13篇

目录

评论

被折叠的  条评论

为什么被折叠?

到【灌水乐园】发言

查看更多评论

添加红包

祝福语

请填写红包祝福语或标题

红包数量

红包个数最小为10个

红包总金额

红包金额最低5元

余额支付

当前余额3.43元

前往充值 >

需支付:10.00元

取消

确定

下一步

知道了

成就一亿技术人!

领取后你会自动成为博主和红包主的粉丝

规则

hope_wisdom 发出的红包

实付元

使用余额支付

点击重新获取

扫码支付

钱包余额

0

抵扣说明:

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

余额充值