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岁以上使用!
午放学抱抱我吗,毕竟,下一次见我就是明年了。