Linux,C,Socket编程原理及简单实例,sanic官方文档解析之蓝图

Socket编程是计算机网络通信中十分重要的一环,指的是通过网络传输实现进程间通信的一种方法。在Linux系统下,开发者可以使用C语言编写Socket程序,通过Socket接口进行网络通信。在此文中,我们将详细介绍Linux C Socket编程的原理及简单实例,并解析sanic官方文档中的蓝图。

一、Socket编程原理

Socket是一种抽象的概念,大多数程序员熟知的是TCP/IP协议族提供的一种基于流的Socket,即TCP Socket。Socket函数库提供了编程接口,使得应用程序可以直接访问传输层协议(如TCP和UDP)来实现网络通信。Socket通过封装了底层的TCP/IP协议,为应用程序提供了一种可靠的网络通信机制。

在Linux系统下,使用Socket编程进行网络通信的步骤如下:

1. 创建Socket对象

在进行Socket编程时,需要先创建Socket对象。Linux系统下,可以使用socket函数创建Socket对象,如下所示:

```c

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

```

其中,domain参数指定协议族,type参数指定Socket类型,protocol参数指定所使用的协议。例如,如果想要创建一个基于TCP协议的Socket对象,则需要使用如下代码:

```c

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

```

2. 绑定Socket对象

创建Socket对象后,需要将Socket对象绑定到一个本地地址和端口上。在Linux系统下,可以使用bind函数进行绑定操作,如下所示:

```c

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

```

其中,sockfd参数指定Socket对象描述符,addr参数指定要绑定的本地地址和端口,addrlen参数指定本地地址结构体长度。

3. 监听连接请求

绑定Socket对象后,需要开始监听连接请求。在Linux系统下,可以使用listen函数进行监听操作,如下所示:

```c

int listen(int sockfd, int backlog);

```

其中,sockfd参数指定Socket对象描述符,backlog参数指定连接队列中最大连接数。

4. 接收连接请求

当有客户端发送连接请求时,需要使用accept函数接收连接请求。accept函数会阻塞主函数,直到有客户端连接成功,如下所示:

```c

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

```

其中,sockfd参数指定Socket对象描述符,addr参数指定客户端地址信息,addrlen参数指定客户端地址结构体长度。

5. 发送、接收数据

当客户端通过Socket连接成功后,就可以使用send和recv函数进行数据的发送和接收,如下所示:

```c

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

```

其中,sockfd参数指定Socket对象描述符,buf参数指定缓冲区地址,len参数指定缓冲区大小,flags参数指定操作方式。

二、Socket编程实例

下面我们给出一个简单的Socket编程实例,用于展示Socket编程的基本操作流程。

本例实现一个简单的基于TCP的服务端和客户端通信,主要包括以下步骤:

1. 创建Socket对象;

2. 绑定Socket对象到本地地址和端口;

3. 监听客户端连接请求;

4. 接收客户端连接请求,建立连接;

5. 使用Socket对象进行数据发送和接收;

6. 关闭Socket对象。

服务端代码如下所示:

```c

#include

#include

#include

#include

#include

#define PORT 8080

int main() {

int server_fd, new_socket, valread;

struct sockaddr_in address;

int opt = 1;

int addrlen = sizeof(address);

char buffer[1024] = {0};

char *hello = "Hello from server";

// 创建Socket对象

if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {

perror("socket failed");

return 0;

}

// 绑定Socket对象到本地地址和端口

if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) {

perror("setsockopt");

return 0;

}

address.sin_family = AF_INET;

address.sin_addr.s_addr = INADDR_ANY;

address.sin_port = htons(PORT);

if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {

perror("bind failed");

return 0;

}

// 监听客户端连接请求

if (listen(server_fd, 3) < 0) {

perror("listen");

return 0;

}

// 接收客户端连接请求,建立连接

if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen))<0) {

perror("accept");

return 0;

}

// 使用Socket对象进行数据发送和接收

valread = read(new_socket, buffer, 1024);

printf("%s\n", buffer);

send(new_socket, hello, strlen(hello), 0);

// 关闭Socket对象

close(new_socket);

close(server_fd);

return 0;

}

```

客户端代码如下所示:

```c

#include

#include

#include

#include

#include

#define PORT 8080

int main() {

int sock = 0, valread;

struct sockaddr_in serv_addr;

char *hello = "Hello from client";

char buffer[1024] = {0};

// 创建Socket对象

if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {

printf("\n Socket creation error \n");

return -1;

}

serv_addr.sin_family = AF_INET;

serv_addr.sin_port = htons(PORT);

// 将IP地址从字符串转换为网络字节序的整数

if(inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr)<=0) {

printf("\nInvalid address/ Address not supported \n");

return -1;

}

// 连接服务端

if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {

printf("\nConnection Failed \n");

return -1;

}

// 使用Socket对象进行数据发送和接收

send(sock, hello, strlen(hello), 0);

printf("Hello message sent\n");

valread = read(sock, buffer, 1024);

printf("%s\n", buffer);

// 关闭Socket对象

close(sock);

return 0;

}

```

三、sanic官方文档解析之蓝图

sanic是一个基于异步Python 3.5+和uvloop的Web框架,类似于Flask,但使用异步编程模型。在sanic中,蓝图是一种组织应用程序的方式,用于将相似的URI分组在一起并使用相同的代码处理它们。以下是sanic官方文档中蓝图的解析:

1. 导入蓝图

在使用蓝图之前,需要先从sanic框架中导入蓝图模块,如下所示:

``` python

from sanic import Blueprint

```

2. 创建蓝图对象

创建蓝图对象时,可以指定蓝图的名称和URL前缀。如下所示:

``` python

bp = Blueprint('my_blueprint', url_prefix='/my_url_prefix')

```

3. 定义请求处理函数

在蓝图对象中,可以使用装饰器定义请求处理函数,如下所示:

``` python

from sanic.response import json

@bp.route('/my_route')

async def my_route(request):

return json({'hello': 'world'})

```

上述代码创建了一个路由,对来自/my_url_prefix/my_route的GET请求返回{'hello': 'world'} JSON响应。

4. 将蓝图注册到应用程序中

将蓝图对象注册到应用程序中,即可开始处理来自蓝图对象注册路径的请求,如下所示:

``` python

from sanic import Sanic

from my_blueprint import bp

app = Sanic(__name__)

app.blueprint(bp)

```

上述代码将my_blueprint对象注册到应用程序中,并将根路由设置为/my_url_prefix。现在,可以开始使用蓝图来组织应用程序代码。

在使用蓝图时,需要注意以下几点:

1. 蓝图对象中使用的装饰器将只对蓝图对象上的路由起作用,而不是全局。

2. 可以在蓝图对象上使用多个装饰器。

3. 在使用蓝图时,需要注意避免使用重复的路由名称和URL前缀,以确保路由名称和URL前缀的唯一性。

总之,在sanic框架中,使用蓝图可以有效地组织应用程序代码,使得代码更加模块化、可读性更强。同时,使用异步编程模型,可以提高应用程序的性能和并发处理能力。

综上,本文详细介绍了Linux C Socket编程的原理及简单实例,并解析了sanic官方文档中蓝图的使用。希望读者可以通过本文了解Socket编程和蓝图的使用,从而更好地进行网络编程和Web框架开发。

购买后如果没出现相关链接,请刷新当前页面!!!
链接失效的请留言 ,我看见了就补上!!!

网站内容来源于互联网,我们将这些信息转载出来的初衷在于分享与学习,这并不意味着我们站点对这些信息的观点或真实性作出认可,我们也不承担对这些信息的责任。
适度游戏益脑,沉迷游戏伤身。 合理安排时间,享受健康生活。适龄提示:适合18岁以上使用!

点赞(4) 打赏

评论列表 共有 1 条评论

花花世界╮许我一生 1年前 回复TA

午放学抱抱我吗,毕竟,下一次见我就是明年了。

立即
投稿
发表
评论
返回
顶部