mysql非阻塞通信协议_阻塞,非阻塞connect()和accept()

非阻塞connect()和accept()

一.select()函数

select()函数准备好读的条件:

1>.套接口有数据可读

2>.该连接的读这一半关闭(也就是接收了FIN的TCP连接)。对这样的套接口进行读操作将不阻塞并返回0(也就是返回EOF)。

3>.该套接口是一个侦听套接口且已完成的连接数不为0。

4>.其上有一个套接口错误待处理,对这样的套接口的读操作将不阻塞并返回-1,并设置errno,可以通过设置SO_ERROR选项调用getsockopt函数获得。

select()函数准备好写的条件:

1>.套接口有可用于写的空间。

2>.该连接的写这一半关闭,对这样的套接口进行写操作将产生SIGPIPE信号。

3>.该套接口使用非阻塞的方式connect建立连接,并且连接已经异步建立,或则connect已经以失败告终。

4>.其上有一个套接口错误待处理。

1

2

3

4

5

二.accept()函数

1.阻塞模式

阻塞模式下调用accept()函数,而且没有新连接时,进程会进入睡眠状态。

2.非阻塞模式

非阻塞模式下调用accept()函数,而且没有新连接时,将返回EWOULDBLOCK错误。

非阻塞模式select() + accept()

sockfd = listen_tcp(); //socket()、bind()、listen()

FD_SET(sockfd, rset);

while(1){

ret = select(sockfd + 1, rset, NULL, NULL, timeout); // 等待某个事件发生:或是新连接、或是数据、或是FIN、或是RST到达

if(select()返回TIMEOUT){ //select()超时

printf("日志打印");

sleep(1);

continue;

}

else if(FD_ISSET(sockfd,&rset)){ //判断句柄是否可读,返回真代表可读,可读代表有新连接。

connfd = accept(sockfd, ...);

}

else if(select()返回错误){

return -1;

}

pthread_create(thread_recv_data, connfd, ...); // 创建线程处理新连接.

close();

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

}

三.connect()函数

1.阻塞模式

客户端调用connect()函数将激发TCP的三路握手过程,但仅在连接建立成功或出错时才返回。返回的错误可能有以下几种情况:

1>.如果TCP客户端没有接收到SYN分节的响应,则返回ETIMEDOUT,阻塞模式的超时时间在75秒(4.4BSD内核)到几分钟之间。

2>.如果对客户的SYN的响应时RST,则表明该服务器主机在我们指定的端口上没有进程在等待与之连接(例如服务器进程也许没有启动),这称为硬错,客

1

2

3

户一接收到RST,马上就返回错误ECONNREFUSED.

3>.如果某客户发出的SYN在中间的路由器上引发了一个目的地不可达ICMP错误,多次尝试发送失败后返回错误号为EHOSTUNREACH或ENETUNREACH.

1

附加:产生RST的三种情况,一是SYN到达某端口但此端口上没有正在侦听的服务器、二是TCP想取消一个已有连接、三是TCP接收了一个根本不存在的连接上的

分节。

2.非阻塞工作模式

调用connect()函数会立刻返回EINPROCESS错误,但TCP通信的三路握手过程正在进行,所以可以使用select函数来检查这个连接是否建立成功。

源自Berkeley的实现有两条与select函数和非阻塞相关的规则:

1

1>.当连接成功建立时,描述字变成可写。

2>.当连接建立出错时,描述字变成即可读又可写。getsockopt()函数的errno == 0表示只可写。

非阻塞模式 select() + connect()

while(1){

ret = connect();

if(errno == EINPROCESS){ //此时TCP的三路握手继续进行

select(...) //等待某个事件发生:或是新连接、或是超时

if(FD_ISSET(sockfd,&wset) ){ //判断句柄可写,不能代表建立连接成功。

getsockopt(...);

if(errno == 0){ //建立连接成功

}

}

else if(select()返回TIMEOUT){

sleep(1);

continue();

}

}

else if(ret == -1){

//Connect failed

}

pthread_create(thread_send_log, ...); //建立线程处理新连接

close();

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

}

https://blog.csdn.net/bobkentblog/article/details/50850724

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要让单片机STM32通过以太网和SQL Server进行通信,需要使用一种中间协议。在这里,我将介绍一种常用的协议——ODBC协议。 ODBC(Open Database Connectivity)是一种开放的数据访问标准,用于在不同的平台上访问不同的数据库。ODBC协议具有良好的可移植性,它可以在Windows、Linux、Unix等不同的操作系统中使用。同时,ODBC协议可以访问多种类型的数据库,包括MySQL、SQL Server、Oracle等。 在STM32中,可以使用一些第三方库来实现ODBC协议的支持。例如,可以使用lwIP库来实现以太网通信,使用unixODBC库来实现ODBC协议的支持。 下面是一个简单的示例代码,展示了如何在STM32中通过以太网和SQL Server进行通信: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <lwip/netif.h> #include <lwip/tcp.h> #include <odbcinst.h> #include <sql.h> #include <sqlext.h> #define SERVER "server_address" #define UID "username" #define PWD "password" #define DATABASE "database_name" void tcp_client_callback(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) { // TODO: 处理接收到的数据 } int main() { struct netif netif; ip4_addr_t ipaddr, netmask, gw; struct tcp_pcb *pcb; BYTE outstr[1024]; SQLHENV henv; SQLHDBC hdbc; SQLHSTMT hstmt; SQLCHAR *conn_str = (SQLCHAR*)"DRIVER={SQL Server};SERVER="SERVER";UID="UID";PWD="PWD";DATABASE="DATABASE";"; SQLCHAR sql_query[1024]; SQLRETURN ret; // 初始化网络接口 netif_add(&netif, &ipaddr, &netmask, &gw, NULL, &ethernetif_init, &tcpip_input); netif_set_default(&netif); netif_set_up(&netif); // 连接数据库 ret = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv); ret = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0); ret = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc); ret = SQLDriverConnect(hdbc, NULL, conn_str, SQL_NTS, NULL, 0, NULL, SQL_DRIVER_NOPROMPT); // 执行查询语句 ret = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt); sprintf(sql_query, "SELECT * FROM table_name"); ret = SQLExecDirect(hstmt, sql_query, SQL_NTS); while (SQLFetch(hstmt) == SQL_SUCCESS) { SQLGetData(hstmt, 1, SQL_C_CHAR, outstr, 1024, NULL); // TODO: 处理查询结果 } // 关闭数据库连接 SQLFreeHandle(SQL_HANDLE_STMT, hstmt); SQLDisconnect(hdbc); SQLFreeHandle(SQL_HANDLE_DBC, hdbc); SQLFreeHandle(SQL_HANDLE_ENV, henv); // 建立TCP连接 pcb = tcp_new(); tcp_bind(pcb, IP_ADDR_ANY, 0); pcb = tcp_connect(pcb, IP_ADDR_BROADCAST, 1234, tcp_client_callback); if (pcb == NULL) { printf("TCP connection failed\n"); return 0; } // 发送数据 tcp_write(pcb, "Hello, world!", 13, 1); // 循环处理网络事件 while (1) { tcpip_input(NULL, NULL); } return 0; } ``` 在这个示例代码中,首先连接了SQL Server数据库,并执行了一个查询语句。查询结果可以通过outstr数组获取。然后建立了一个TCP连接,并发送了一条数据。最后进入了一个无限循环,不断处理网络事件。 需要注意的是,这个示例代码仅仅是一个基础的框架,具体的实现需要根据实际需求进行调整。同时,也需要注意安全性问题,例如数据库连接信息的保护,以及数据传输过程中的加密等。

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值