网络编程

学习笔记(五)之网络编程:

协议:公共的约定
OSI七层 理想模型
应用层 http:超文本传输协议 telnet:远程登录协议 SMTP: FTP:文本传输协议
表示层 正文格式约定 GB2312 UTF_8
会话层 负责建立和断开通信的时机
传输层 TCP UDP port
网络层 ip ipv4 ipv6
数据链路层 mac地址 交换机 arp地址解析协议 rarp逆向地址解析协议
物理层 网线 中继器 集线器

TCP/IP四层 工业标准
应用层

传输层

网络层

网络接口和物理层

网关:实现内外网隔离
路由器:主干道上的路由器 有路由功能(从哪来到哪去)
家用路由器: 网关功能 路由功能 DNS映射表 wifi 交换机功能 DHCP(动态ip地址分配)

DNS:域名解析服务 域名-->ip地址
经典DNS:114.114.114.114 电信 8.8.8.8谷歌 223.5.5.5 223.6.6.6 阿里云
浏览器直接解析
DDNS(动态域名解析)
经典域名:www.baidu.com www.360buy.com

port(端口号):16bit位组成 0~65535
用于计算机中区分不同进程
TCP和UDP各有一套自己的端口号(0~65535)
0~1023:知名端口
1024~49151:注册端口
49152~65535:私有端口 开发和测试时自己使用

mac地址(硬件地址): 12位16进制数组成 一共48个bit位

ip地址: 点分十进制 192.168.2.111 以8bit为一组划分成四组,以'.'隔开
ipv4:32bit组成
网络号:
主机号: 全0全1不可用 全0就代表网络号,全1表示广播地址
主机号为1一般代表网关
mask:子网掩码 子网划分使用 ip & mask == 网络号

四类ip
A:网络号占8位 ,主机号24位 2^24 - 2
网络号以 0b 0 开始 : 0b 0 000 0000~0b 0 111 1111 0~127

B:网络号占16位,主机号16位 2^16 - 2
网络号以0b 10 开始 : 0b 10 00 0000.0000 0000 128.0
0b 10 11 1111.1111 1111 191.255

C:网络号占24位,主机号8位 2^8-2
网络号以0b 110 开始 : 0b 110 0 0000.0000 0000.0000 0000 192.0.0
0b 110 1 1111.1111 1111.1111 1111 223.255.255

D:不做网络号和主机号划分
0b 1110 开始 可以用于尝试组播

E:剩余部分 网络测试使用

特殊ip地址:
127.0.0.1 本机回环地址
局域网地址:
A:10.xxx.xxx.xxx
B:172.16.xxx.xxx ~ 172.31.xxx.xxx
C:192.168.xxx.xxx

网络编程: TCP UDP
TCP(类比:打电话):有连接 可靠的 无乱序 无出错 无丢失
UDP(类比:发短信):无连接的 不可靠的 有乱序 有出错 有丢失

UDP编程:
服务器 客户端
socket:编程接口 man 2
ip地址:
port端口号:
字节序: 大端序 低地址存放高字节 网络设备
小端序 低地址存放低字节 个人PC

UDP服务器:
socket man 7 ip
int socket(int domain, int type, int protocol);
功能:创建一个编程接口,并返回文件描述符
参数:1.协议族 AF_INET ipv4;2.套接字类型 SOCK_DGRAM 数据报(UDP) SOCK_STREAM 流式(TCP) SOCK_RAM 原始;3.协议号 填0自动匹配
返回值:成功返回文件描述符,失败返回-1,并设置errno号

bind
int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
功能:绑定ip和port
参数:1.socket返回的文件描述符 2.地址结构体 (填充新的地址结构体并强转) 3.地址结构体的长度
返回值:成功返回0,失败返回-1,并设置errno号

老的地址结构体: man 2 bind
struct sockaddr {
sa_family_t sa_family;
char sa_data[14];
}
新的地址结构体: man 7 ip Address Format
struct sockaddr_in {
sa_family_t sin_family; /* address family: AF_INET */ 协议族
in_port_t sin_port; /* port in network byte order */ 大端序的port
struct in_addr sin_addr; /* internet address */ 大端序的ip地址
};

/* Internet address. */
struct in_addr {
uint32_t s_addr; /* address in network byte order */
};

字节序转换函数:
htons host to network short
uint16_t htons(uint16_t hostshort);
参数:小端序的port
返回值:大端序的port

htonl host to network long
uint32_t htonl(uint32_t hostlong);
参数:小端序的ip数值
返回值:大端序的ip数值

ntohs network to host short
uint16_t ntohs(uint16_t netshort);
参数:大端序port
返回值:小端序的port

inet_addr: ip字符串-->小端ip数值-->大端ip数值
in_addr_t inet_addr(const char *cp);
参数:ip地址字符串
返回值:大端序的ip地址数值

inet_ntoa network to ascii 大端ip数值-->小端ip数值-->ip字符串
char *inet_ntoa(struct in_addr in);
参数:大端的ip的结构体!!!
返回值:ip字符串

注:
recvfrom就是read二次封装
read
ssize_t read(int fd, void *buf, size_t count);

recvfrom
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr,socklen_t *addrlen);
参数:1.socket返回的文件描述符 2.应用层准备的buf(接收从内核中获取的数据) 3.buf的大小 4.填0 默认阻塞
5.客户端的地址结构体(不关心填NULL) 6.客户端的地址结构体的长度的地址(不关心填NULL)
返回值:
>0 真实获取的数据字节数
==0 数据获取完毕
-1 失败,并设置errno号

UDP客户端
socket

地址结构体需求:服务器的地址结构体
bind? 可有可无

while(1)
{
sendto
}

sendto:
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);
参数:1.socket返回的文件描述符 2.即将发送的数据 3.真实写入数据的长度 4.0
5.服务器的地址结构体 6.服务器的地址结构体长度

 1 #include <stdio.h>
 2 #include <sys/types.h>           /* See NOTES */
 3 #include <sys/socket.h>
 4 #include <arpa/inet.h>
 5 #include <netinet/in.h>
 6 #include <netinet/ip.h> /* superset of previous */
 7 #include <stdlib.h>
 8 #include <strings.h>
 9 
10 int main(int argc, const char *argv[])
11 {
12     char buf[128];
13     //打开编程接口 socket
14     int udp_socket;
15     udp_socket = socket(AF_INET, SOCK_DGRAM, 0);
16     if(udp_socket == -1)
17     {
18         perror("fail to socket");
19         exit(1);
20     }
21 
22     //填充地址结构体
23     struct sockaddr_in ser_addr,cli_addr;
24 
25     ser_addr.sin_family = AF_INET;
26     ser_addr.sin_port = htons(50000); 
27     ser_addr.sin_addr.s_addr = inet_addr("192.168.2.192");
28 
29     //绑定ser ip和port  bind
30     if(-1 == bind(udp_socket,(struct sockaddr *)&ser_addr,sizeof(ser_addr)))
31     {
32         perror("fail to bind");
33         exit(1);
34     }
35 
36     socklen_t len = sizeof(cli_addr);
37 
38     while(1)
39     {
40         bzero(buf,sizeof(buf));
41         //recvfrom
42         if(-1 == recvfrom(udp_socket,buf,sizeof(buf),0,(struct sockaddr*)&cli_addr,&len))
43         {
44             perror("fail to recvfrom");
45             exit(1);
46         }
47         if(strncmp(buf,"quit",4) == 0)
48         {
49             printf("peer is shutdown!\n");
50             continue;
51         }
52         
53         printf("cli_ip:%s cli_port:%d recv:%s\n",inet_ntoa(cli_addr.sin_addr),ntohs(cli_addr.sin_port),buf);
54     }
55 
56     return 0;
57 }
udp_ser
 1 #include <stdio.h>
 2 #include <sys/types.h>           /* See NOTES */
 3 #include <sys/socket.h>
 4 #include <arpa/inet.h>
 5 #include <netinet/in.h>
 6 #include <netinet/ip.h> /* superset of previous */
 7 #include <stdlib.h>
 8 #include <strings.h>
 9 #include <string.h>
10 
11 int main(int argc, const char *argv[])
12 {
13     char buf[128];
14     //打开编程接口 socket
15     int udp_socket;
16     udp_socket = socket(AF_INET, SOCK_DGRAM, 0);
17     if(udp_socket == -1)
18     {
19         perror("fail to socket");
20         exit(1);
21     }
22 
23     //填充地址结构体
24     struct sockaddr_in ser_addr;
25 
26     ser_addr.sin_family = AF_INET;
27     ser_addr.sin_port = htons(50000); 
28     ser_addr.sin_addr.s_addr = inet_addr("192.168.2.192");
29 
30     //bind可有可无
31     
32     while(1)
33     {
34         bzero(buf,sizeof(buf));
35         //sendto
36         fgets(buf,sizeof(buf),stdin);
37 
38         sendto(udp_socket,buf,strlen(buf),0,(struct sockaddr*)&ser_addr,sizeof(ser_addr));
39 
40         if(strncmp(buf,"quit",4) == 0)
41         {
42             break;
43         }
44     }
45 
46     return 0;
47 }
udp_cli

 

nc命令:模拟客户端和服务器
-l:代表服务器 不加代表客户端
-u:代表udp 不加代表tcp
格式:
nc 选项 ip地址 port
例如:
udp客户端
nc -u 服务器ip 服务器port
udp服务器
nc -l -u 服务器ip 服务器port

UDP练习:
1.echo回声服务器

 1 #include <stdio.h>
 2 #include <sys/socket.h>
 3 #include <sys/types.h>           /* See NOTES */
 4 #include <netinet/in.h>
 5 #include <netinet/ip.h> /* superset of previous */
 6 #include <arpa/inet.h>
 7 #include <stdlib.h>
 8 #include <string.h>
 9 
10 int main(int argc, const char *argv[])
11 {
12     char recv_buf[128];
13     char send_buf[128];
14     //socket  
15     int udp_socket;
16     udp_socket = socket(AF_INET, SOCK_DGRAM, 0);
17     if(udp_socket == -1)
18     {
19         perror("fail to socket");
20         exit(1);
21     }
22     
23     //struct sockaddr_in
24     struct sockaddr_in ser_addr,cli_addr,peeraddr;
25 
26     ser_addr.sin_family = AF_INET;
27     ser_addr.sin_port = htons(50000);
28     ser_addr.sin_addr.s_addr = inet_addr("192.168.2.192");
29 
30     //bind
31     if(-1 == bind(udp_socket,(struct sockaddr*)&ser_addr,sizeof(ser_addr)))    
32     {
33         perror("fail to open");
34         exit(1);
35     }
36     
37     socklen_t len = sizeof(cli_addr);
38 
39     while(1)
40     {
41         memset(recv_buf,0,sizeof(recv_buf));
42         if(-1 == recvfrom(udp_socket,recv_buf,sizeof(recv_buf),0,(struct sockaddr*)&cli_addr,&len))
43         {
44             perror("fail to recvfrom");
45             exit(1);
46         }    
47 
48         memset(send_buf,0,sizeof(send_buf));
49         sprintf(send_buf,"ip:%s port:%d say:%s\n",inet_ntoa(cli_addr.sin_addr),ntohs(cli_addr.sin_port),recv_buf);
50 
51         peeraddr.sin_family = AF_INET;
52         peeraddr.sin_port = htons(60000); //客户端都默认绑定60000端口号
53         int i;
54         for(i = 2;i <= 254;i++)
55         {
56             peeraddr.sin_addr.s_addr = htonl((192 << 24) + (168 << 16) + (2 << 8) + i);
57             sendto(udp_socket,send_buf,strlen(send_buf),0,(struct sockaddr*)&peeraddr,sizeof(peeraddr));
58         }
59 
60     }
61     return 0;
62 }
echo

2.UDP的伪广播

 1 #include <stdio.h>
 2 #include <sys/types.h>           /* See NOTES */
 3 #include <sys/socket.h>
 4 #include <arpa/inet.h>
 5 #include <netinet/in.h>
 6 #include <netinet/ip.h> /* superset of previous */
 7 #include <stdlib.h>
 8 #include <strings.h>
 9 #include <string.h>
10 
11 int main(int argc, const char *argv[])
12 {
13     char buf[128];
14     //打开编程接口 socket
15     int udp_socket;
16     udp_socket = socket(AF_INET, SOCK_DGRAM, 0);
17     if(udp_socket == -1)
18     {
19         perror("fail to socket");
20         exit(1);
21     }
22 
23     struct sockaddr_in ser_addr;
24     ser_addr.sin_family = AF_INET;
25     ser_addr.sin_port = htons(50000); 
26     ser_addr.sin_addr.s_addr = inet_addr("192.168.2.255");
27 
28     int optval = 1;
29     if(-1 == setsockopt(udp_socket,SOL_SOCKET,SO_BROADCAST,&optval,sizeof(optval)))
30     {
31         perror("fail to broadcast");
32         exit(1);
33     }
34     
35     while(1)
36     {
37         bzero(buf,sizeof(buf));
38         //sendto
39         fgets(buf,sizeof(buf),stdin);
40 
41         sendto(udp_socket,buf,strlen(buf),0,(struct sockaddr*)&ser_addr,sizeof(ser_addr));
42 
43         }
44 
45     return 0;
46 }
udp_broadcast

 

模拟客户端
发送:nc -u 服务器ip 服务器port
nc -u 192.168.2.192 50000
接收:nc -u -l 自己的ip 自己的端口60000


sprintf
int sprintf(char *str, const char *format, ...);
参数:1.准备的buf 2.输出格式控制串 3.输出表
功能:将内容按指定格式输出到指定的buf中

TCP编程:
TCP服务器: man 7 tcp 描述服务器和客户端的框架函数 先开后关
socket

bind绑定服务器ip和port

listen :将socket编程监听套接字 用于监听即将到来的连接请求
int listen(int sockfd, int backlog);
参数:1.socket返回的文件描述
2.等待队列的长度 5 高版本内核对该数值仅做参考值,会自动扩展 当内核很忙,且等待队列全满时,客户端可能
会收到一个连接失败的错误 ECONNREFUSED /* Connection refused */
返回值:成功返回0,失败返回-1,并设置errno号

while(1) 循环建立连接
{
accept :
1.从等待队列中抽取第一个成员建立连接(依赖于listen的监听套接字)
2.建立连接后创建了一个新的连接套接字(用于数据交换),并返回该套接字的文件描述符
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
参数:1.socket返回的处于监听模式的套接字的文件描述 (目前是监听模式) 2.客户端的地址结构体 3.对方地址结构体长度的指针
返回值:成功返回连接套接字的文件描述符 ,失败返回-1,并设置errno号

while(1) 建立连接后循环接收数据 利用recv返回值退出
{
recv :
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
参数:1.accept返回的连接套接字文件描述符 2.应用层准备的buf 3.buf的长度 4.填0 默认阻塞
返回值:
<0 出错设置errno
==0 数据读取完毕
>0 真实读取数据的个数
}
}

 1 #include <stdio.h>
 2 #include <sys/socket.h>
 3 #include <sys/types.h>           /* See NOTES */
 4 #include <netinet/in.h>
 5 #include <netinet/ip.h> /* superset of previous */
 6 #include <stdlib.h>
 7 #include <arpa/inet.h>
 8 #include <string.h>
 9 
10 int main(int argc, const char *argv[])
11 {
12     char buf[128];
13     int recv_ret;
14     //socket  使用流式套接字
15     int tcp_socket,con_socket;
16     tcp_socket = socket(AF_INET, SOCK_STREAM, 0);
17     if(tcp_socket == -1)
18     {
19         perror("fail to socket");
20         exit(1);
21     }
22 
23     int optval = 1;
24     //setsockopt  设置套接字属性
25     if(-1 == setsockopt(tcp_socket,SOL_SOCKET,SO_REUSEADDR,&optval,sizeof(optval)))
26     {
27         perror("fail to setsockopt");
28         exit(1);
29     }
30 
31     //struct sockaddr_in
32     struct sockaddr_in ser_addr,cli_addr;
33 
34     ser_addr.sin_family = AF_INET;
35     ser_addr.sin_port = htons(50000);
36     ser_addr.sin_addr.s_addr = inet_addr("0.0.0.0");
37     //0.0.0.0 本机ip地址自动适配
38 
39     //bind   服务器ip和port
40     if(-1 == bind(tcp_socket,(struct sockaddr*)&ser_addr,sizeof(ser_addr)))
41     {
42         perror("fail to bind");
43         exit(1);
44     }
45 
46     //listen  将socket变成监听模式
47     if(-1 == listen(tcp_socket,5))
48     {
49         perror("fail to listen");
50         exit(1);
51     }
52 
53     socklen_t len = sizeof(cli_addr);
54 
55     while(1)
56     {
57         //accept 建立连接
58         con_socket = accept(tcp_socket,(struct sockaddr*)&cli_addr,&len);
59         if(con_socket == -1)
60         {
61             perror("fail to accept");
62             exit(1);
63         }
64     
65         printf("%s %d is connnecting!\n",inet_ntoa(cli_addr.sin_addr),ntohs(cli_addr.sin_port));
66         
67         while(1)
68         {
69             memset(buf,0,sizeof(buf));
70             //recv 接收消息
71             recv_ret = recv(con_socket,buf,sizeof(buf),0);
72             if(recv_ret < 0)
73             {
74                 perror("fail to recv");
75                 exit(1);
76             }
77             else if(recv_ret == 0) //数据接收完毕  
78             {
79                 printf("%s %d is shutdown!\n",inet_ntoa(cli_addr.sin_addr),ntohs(cli_addr.sin_port));
80                 break;
81             }
82             else
83             {
84                 printf("recv:%s\n",buf);
85             }
86         }
87     }
88     return 0;
89 }
tcp_ser

 

TCP客户端:
socket

服务器的地址结构体 ip和port
bind?可有可无

connect :发送连接请求
int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
参数:1.socket返回的文件描述符 2.服务器的地址结构体 3.服务器的地址结构体长度
返回值:成功返回0,失败返回-1,并设置errno号

while(1)
{
send
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
参数:1.socket返回的文件描述符 2.将要发送的数据buf 3.buf的大小(真实发送的数据长度) 4.0
返回值:成功返回真实发送的字节数,失败返回-1,并设置errno号
}

 1 #include <stdio.h>
 2 #include <sys/socket.h>
 3 #include <sys/types.h>           /* See NOTES */
 4 #include <netinet/in.h>
 5 #include <netinet/ip.h> /* superset of previous */
 6 #include <arpa/inet.h>
 7 #include <stdlib.h>
 8 #include <string.h>
 9 
10 int main(int argc, const char *argv[])
11 {
12     if(argc != 3)
13     {
14         fprintf(stderr,"please input port and ip!\n");
15         exit(1);
16     }
17     char buf[128];
18     //socket
19     int tcp_socket;
20     tcp_socket = socket(AF_INET, SOCK_STREAM, 0);
21     if(tcp_socket == -1)
22     {
23         perror("fail to socket");
24         exit(1);
25     }
26     
27     //服务器地址结构体
28     struct sockaddr_in ser_addr;
29 
30     ser_addr.sin_family = AF_INET;
31     ser_addr.sin_port = htons(atoi(argv[1]));
32     ser_addr.sin_addr.s_addr = inet_addr(argv[2]);
33 
34     //connect
35     if(-1 == connect(tcp_socket,(struct sockaddr*)&ser_addr,sizeof(ser_addr)))
36     {
37         perror("fail to connect");
38         exit(1);
39     }
40     
41     while(1)
42     {
43         memset(buf,0,sizeof(buf));
44         
45         fgets(buf,sizeof(buf),stdin);
46 
47         if(strncmp(buf,"quit",4) == 0)
48             break;
49         //send 
50         send(tcp_socket,buf,strlen(buf),0);
51     }
52 
53 
54 
55     return 0;
56 }
tcp_cli

 

错误现象:客户端有链接时,服务器却异常退出,再次登录服务器会出现port冲突的情况
1.等一段时间就行了
2.修改端口号
3.使用函数setsockopt
setsockopt :根据文件描述符设置socket属性
int setsockopt(int sockfd, int level, int optname,const void *optval, socklen_t optlen);
参数:1.socket返回的文件描述符 2.填写SOL_SOCKET
3.SO_REUSEADDR(bind时会强制绑定port) man 7 socket Socket Options
4.决定功能是否开启 int a = 1 开启 0关闭 取地址放入 5.第四个参数的长度
返回值:成功返回0,失败返回-1,并设置errno号

 1 #include <stdio.h>
 2 #include <sys/socket.h>
 3 #include <sys/types.h>           /* See NOTES */
 4 #include <netinet/in.h>
 5 #include <netinet/ip.h> /* superset of previous */
 6 #include <stdlib.h>
 7 #include <arpa/inet.h>
 8 #include <string.h>
 9 
10 int main(int argc, const char *argv[])
11 {
12     char buf[128];
13     int recv_ret;
14     //socket  使用流式套接字
15     int tcp_socket,con_socket;
16     tcp_socket = socket(AF_INET, SOCK_STREAM, 0);
17     if(tcp_socket == -1)
18     {
19         perror("fail to socket");
20         exit(1);
21     }
22 
23     int optval = 1;
24     //setsockopt  设置套接字属性
25     if(-1 == setsockopt(tcp_socket,SOL_SOCKET,SO_REUSEADDR,&optval,sizeof(optval)))
26     {
27         perror("fail to setsockopt");
28         exit(1);
29     }
30 
31     //struct sockaddr_in
32     struct sockaddr_in ser_addr,cli_addr;
33 
34     ser_addr.sin_family = AF_INET;
35     ser_addr.sin_port = htons(50000);
36     ser_addr.sin_addr.s_addr = inet_addr("0.0.0.0");
37     //0.0.0.0 本机ip地址自动适配
38 
39     //bind   服务器ip和port
40     if(-1 == bind(tcp_socket,(struct sockaddr*)&ser_addr,sizeof(ser_addr)))
41     {
42         perror("fail to bind");
43         exit(1);
44     }
45 
46     //listen  将socket变成监听模式
47     if(-1 == listen(tcp_socket,5))
48     {
49         perror("fail to listen");
50         exit(1);
51     }
52 
53     socklen_t len = sizeof(cli_addr);
54 
55     while(1)
56     {
57         //accept 建立连接
58         con_socket = accept(tcp_socket,(struct sockaddr*)&cli_addr,&len);
59         if(con_socket == -1)
60         {
61             perror("fail to accept");
62             exit(1);
63         }
64     
65         printf("%s %d is connnecting!\n",inet_ntoa(cli_addr.sin_addr),ntohs(cli_addr.sin_port));
66         
67         while(1)
68         {
69             memset(buf,0,sizeof(buf));
70             //recv 接收消息
71             recv_ret = recv(con_socket,buf,sizeof(buf),0);
72             if(recv_ret < 0)
73             {
74                 perror("fail to recv");
75                 exit(1);
76             }
77             else if(recv_ret == 0) //数据接收完毕  
78             {
79                 printf("%s %d is shutdown!\n",inet_ntoa(cli_addr.sin_addr),ntohs(cli_addr.sin_port));
80                 break;
81             }
82             else
83             {
84                 printf("recv:%s\n",buf);
85             }
86         }
87     }
88     return 0;
89 }
tcp_ser

 

TCP建立连接和断开连接的方式:
安装wireshark:
sudo apt-get install wireshark

使用方法:
运行sudo wireshark

选择网卡any 输入例如: udp.port == 50000 进行筛选

三次握手:
客户端发送一个同部位包裹 SYN=1 服务器收到后返回应答包裹ACK=1并发送SYN = 1请求 客户端收到后回复ACk=1
四次挥手:
客户端发送一个结束位包裹 FIN=1 服务器收到后返回应答包裹ACK=1并发送结束为包裹FIN=1 客户端收到后回复ACK=1

练习:文件传输
1.按字节传输

  1 #include <stdio.h>
  2 #include <sys/socket.h>
  3 #include <sys/types.h>           /* See NOTES */
  4 #include <netinet/in.h>
  5 #include <sys/stat.h>
  6 #include <netinet/ip.h> /* superset of previous */
  7 #include <stdlib.h>
  8 #include <fcntl.h>
  9 #include <arpa/inet.h>
 10 #include <string.h>
 11 
 12 int main(int argc, const char *argv[])
 13 {
 14     char buf;
 15     int recv_ret;
 16 
 17     //打开文件 open
 18     int fd;
 19     fd = open("./recvfile.txt",O_WRONLY | O_CREAT | O_TRUNC,0666);
 20     if(fd == -1)
 21     {
 22         perror("fail to open");
 23         exit(1);
 24     }
 25 
 26     //socket  使用流式套接字
 27     int tcp_socket,con_socket;
 28     tcp_socket = socket(AF_INET, SOCK_STREAM, 0);
 29     if(tcp_socket == -1)
 30     {
 31         perror("fail to socket");
 32         exit(1);
 33     }
 34 
 35     int optval = 1;
 36     //setsockopt  设置套接字属性
 37     if(-1 == setsockopt(tcp_socket,SOL_SOCKET,SO_REUSEADDR,&optval,sizeof(optval)))
 38     {
 39         perror("fail to setsockopt");
 40         exit(1);
 41     }
 42 
 43     //struct sockaddr_in
 44     struct sockaddr_in ser_addr,cli_addr;
 45 
 46     ser_addr.sin_family = AF_INET;
 47     ser_addr.sin_port = htons(50000);
 48     ser_addr.sin_addr.s_addr = inet_addr("0.0.0.0");
 49     //0.0.0.0 本机ip地址自动适配
 50 
 51     //bind   服务器ip和port
 52     if(-1 == bind(tcp_socket,(struct sockaddr*)&ser_addr,sizeof(ser_addr)))
 53     {
 54         perror("fail to bind");
 55         exit(1);
 56     }
 57 
 58     //listen  将socket变成监听模式
 59     if(-1 == listen(tcp_socket,5))
 60     {
 61         perror("fail to listen");
 62         exit(1);
 63     }
 64 
 65     socklen_t len = sizeof(cli_addr);
 66 
 67     //accept 建立连接
 68     con_socket = accept(tcp_socket,(struct sockaddr*)&cli_addr,&len);
 69     if(con_socket == -1)
 70     {
 71         perror("fail to accept");
 72         exit(1);
 73     }
 74 
 75 
 76     while(1)
 77     {
 78 
 79         //recv 接收消息
 80         recv_ret = recv(con_socket,&buf,1,0);
 81         if(recv_ret < 0)
 82         {
 83             perror("fail to recv");
 84             exit(1);
 85         }
 86         else if(recv_ret == 0) //数据接收完毕  
 87         {
 88             break;
 89         }
 90         else
 91         {
 92             write(fd,&buf,1);
 93         }
 94     }
 95 
 96     close(fd);
 97     close(tcp_socket);
 98     close(con_socket);
 99     return 0;
100 }
fgetc_recv
 1 #include <stdio.h>
 2 #include <sys/socket.h>
 3 #include <sys/types.h>           /* See NOTES */
 4 #include <netinet/in.h>
 5 #include <netinet/ip.h> /* superset of previous */
 6 #include <arpa/inet.h>
 7 #include <stdlib.h>
 8 #include <string.h>
 9 #include <sys/stat.h>
10 #include <fcntl.h>
11 
12 int main(int argc, const char *argv[])
13 {
14     if(argc != 3)
15     {
16         fprintf(stderr,"please input port and ip!\n");
17         exit(1);
18     }
19 
20     //打开文件  open
21     int fd;
22     fd = open("./1.txt",O_RDONLY);
23     if(fd == -1)
24     {
25         perror("fail to open");
26         exit(1);
27     }
28 
29 
30     char buf;
31     //socket
32     int tcp_socket;
33     tcp_socket = socket(AF_INET, SOCK_STREAM, 0);
34     if(tcp_socket == -1)
35     {
36         perror("fail to socket");
37         exit(1);
38     }
39 
40     //服务器地址结构体
41     struct sockaddr_in ser_addr;
42 
43     ser_addr.sin_family = AF_INET;
44     ser_addr.sin_port = htons(atoi(argv[1]));
45     ser_addr.sin_addr.s_addr = inet_addr(argv[2]);
46 
47     //connect
48     if(-1 == connect(tcp_socket,(struct sockaddr*)&ser_addr,sizeof(ser_addr)))
49     {
50         perror("fail to connect");
51         exit(1);
52     }
53 
54     int ret_read;
55     while(1)
56     {
57 
58         ret_read = read(fd,&buf,1);
59         if(ret_read == -1)
60         {
61             perror("fail to read");
62             exit(1);
63         }
64         else if(ret_read == 0)
65         {
66             break;
67         }
68         else
69         {
70             //send 
71             send(tcp_socket,&buf,1,0);
72         }
73     }
74 
75     close(fd);
76     close(tcp_socket);
77 
78     return 0;
79 }
fgetc_send

2.按块方式传递

 1 #include <stdio.h>
 2 #include <sys/socket.h>
 3 #include <sys/types.h>           /* See NOTES */
 4 #include <sys/stat.h>
 5 #include <fcntl.h>
 6 #include <netinet/in.h>
 7 #include <netinet/ip.h> /* superset of previous */
 8 #include <stdlib.h>
 9 #include <arpa/inet.h>
10 #include <string.h>
11 
12 int main(int argc, const char *argv[])
13 {
14     //open 
15     int fd;
16     fd = open("./5.jpg",O_WRONLY | O_CREAT | O_TRUNC,0666);
17     if(fd == -1)
18     {
19         perror("fail to open");
20         exit(1);
21     }
22 
23     char buf[128];
24     int recv_ret;
25     //socket  使用流式套接字
26     int tcp_socket,con_socket;
27     tcp_socket = socket(AF_INET, SOCK_STREAM, 0);
28     if(tcp_socket == -1)
29     {
30         perror("fail to socket");
31         exit(1);
32     }
33 
34 
35     //struct sockaddr_in
36     struct sockaddr_in ser_addr,cli_addr;
37 
38     ser_addr.sin_family = AF_INET;
39     ser_addr.sin_port = htons(50000);
40     ser_addr.sin_addr.s_addr = inet_addr("0.0.0.0");
41     //0.0.0.0 本机ip地址自动适配
42 
43     //bind   服务器ip和port
44     if(-1 == bind(tcp_socket,(struct sockaddr*)&ser_addr,sizeof(ser_addr)))
45     {
46         perror("fail to bind");
47         exit(1);
48     }
49 
50     //listen  将socket变成监听模式
51     if(-1 == listen(tcp_socket,5))
52     {
53         perror("fail to listen");
54         exit(1);
55     }
56 
57     socklen_t len = sizeof(cli_addr);
58 
59     //accept 建立连接
60     con_socket = accept(tcp_socket,(struct sockaddr*)&cli_addr,&len);
61     if(con_socket == -1)
62     {
63         perror("fail to accept");
64         exit(1);
65     }
66 
67 
68     while(1)
69     {
70         memset(buf,0,sizeof(buf));
71         //recv 接收消息
72         recv_ret = recv(con_socket,buf,sizeof(buf),0);
73         if(recv_ret < 0)
74         {
75             perror("fail to recv");
76             exit(1);
77         }
78         else if(recv_ret == 0) //数据接收完毕  
79         {
80 
81             break;
82         }
83         else
84         {
85             write(fd,buf,recv_ret);                
86         }
87     }
88     return 0;
89 }
fgets_recv
 1 #include <stdio.h>
 2 #include <sys/socket.h>
 3 #include <sys/types.h>           /* See NOTES */
 4        #include <sys/stat.h>
 5        #include <fcntl.h>
 6 #include <netinet/in.h>
 7 #include <netinet/ip.h> /* superset of previous */
 8 #include <arpa/inet.h>
 9 #include <stdlib.h>
10 #include <string.h>
11 
12 int main(int argc, const char *argv[])
13 {
14     if(argc != 3)
15     {
16         fprintf(stderr,"please input port and ip!\n");
17         exit(1);
18     }
19 
20     //open read_only
21     int fd;
22     fd = open("./3.jpg",O_RDONLY);
23     if(fd == -1)
24     {
25         perror("fail to open");
26         exit(1);
27     }
28 
29 
30 
31     char buf[128];
32     //socket
33     int tcp_socket;
34     tcp_socket = socket(AF_INET, SOCK_STREAM, 0);
35     if(tcp_socket == -1)
36     {
37         perror("fail to socket");
38         exit(1);
39     }
40     
41     //服务器地址结构体
42     struct sockaddr_in ser_addr;
43 
44     ser_addr.sin_family = AF_INET;
45     ser_addr.sin_port = htons(atoi(argv[1]));
46     ser_addr.sin_addr.s_addr = inet_addr(argv[2]);
47 
48     //connect
49     if(-1 == connect(tcp_socket,(struct sockaddr*)&ser_addr,sizeof(ser_addr)))
50     {
51         perror("fail to connect");
52         exit(1);
53     }
54     
55     int ret_read;
56 
57     while(1)
58     {
59         memset(buf,0,sizeof(buf));
60 
61         ret_read = read(fd,buf,sizeof(buf));
62         if(ret_read < 0)
63         {
64             perror("fail to read");
65             exit(1);
66         }
67         else if(ret_read == 0)
68         {
69             break;
70         }
71         else
72         {
73              //send   读多少写多少
74             send(tcp_socket,buf,ret_read,0);
75         }
76     }
77 
78     close(fd);
79     close(tcp_socket);
80 
81     return 0;
82 }
fgets_send

3.按结构体方式传递(要求文件名一同传递)

 1 #define HQ_FILENAME 1
 2 #define HQ_FILEDATA 2
 3 
 4 
 5 typedef struct a
 6 {
 7     int type; //内容类型
 8     int length;//真实发送的数据长度
 9     char buf[128];//正文内容
10 }node_t;
file_h
  1 #include <stdio.h>
  2 #include <sys/socket.h>
  3 #include <sys/types.h>           /* See NOTES */
  4 #include <netinet/in.h>
  5 #include <netinet/ip.h> /* superset of previous */
  6 #include <stdlib.h>
  7 #include <sys/stat.h>
  8 #include <fcntl.h>
  9 #include <arpa/inet.h>
 10 #include <string.h>
 11 
 12 #include "file.h"
 13 
 14 
 15 int main(int argc, const char *argv[])
 16 {
 17     int fd;
 18     node_t *p = malloc(sizeof(node_t));
 19     int recv_ret;
 20     //socket  使用流式套接字
 21     int tcp_socket,con_socket;
 22     tcp_socket = socket(AF_INET, SOCK_STREAM, 0);
 23     if(tcp_socket == -1)
 24     {
 25         perror("fail to socket");
 26         exit(1);
 27     }
 28 
 29     int optval = 1;
 30     //setsockopt  设置套接字属性
 31     if(-1 == setsockopt(tcp_socket,SOL_SOCKET,SO_REUSEADDR,&optval,sizeof(optval)))
 32     {
 33         perror("fail to setsockopt");
 34         exit(1);
 35     }
 36 
 37     //struct sockaddr_in
 38     struct sockaddr_in ser_addr,cli_addr;
 39 
 40     ser_addr.sin_family = AF_INET;
 41     ser_addr.sin_port = htons(50000);
 42     ser_addr.sin_addr.s_addr = inet_addr("0.0.0.0");
 43     //0.0.0.0 本机ip地址自动适配
 44 
 45     //bind   服务器ip和port
 46     if(-1 == bind(tcp_socket,(struct sockaddr*)&ser_addr,sizeof(ser_addr)))
 47     {
 48         perror("fail to bind");
 49         exit(1);
 50     }
 51 
 52     //listen  将socket变成监听模式
 53     if(-1 == listen(tcp_socket,5))
 54     {
 55         perror("fail to listen");
 56         exit(1);
 57     }
 58 
 59     socklen_t len = sizeof(cli_addr);
 60 
 61     //accept 建立连接
 62     con_socket = accept(tcp_socket,(struct sockaddr*)&cli_addr,&len);
 63     if(con_socket == -1)
 64     {
 65         perror("fail to accept");
 66         exit(1);
 67     }
 68 
 69     while(1)
 70     {
 71         memset(p,0,sizeof(node_t));
 72         //recv 接收消息
 73         recv_ret = recv(con_socket,p,sizeof(node_t),0);
 74         if(recv_ret < 0)
 75         {
 76             perror("fail to recv");
 77             exit(1);
 78         }
 79         else if(recv_ret == 0) //数据接收完毕  
 80         {
 81             break;
 82         }
 83         else
 84         {
 85             //open
 86             if(p->type == HQ_FILENAME)
 87             {
 88                 char pathname[128];
 89                 memset(pathname,0,sizeof(pathname));
 90                 sprintf(pathname,"./%s",p->buf);
 91 
 92                 fd = open(pathname,O_WRONLY | O_CREAT | O_TRUNC,0666);
 93                 if(fd == -1)
 94                 {
 95                     perror("fail to open");
 96                     exit(1);
 97                 }
 98             }
 99             else if(p->type == HQ_FILEDATA)
100             {
101                 write(fd,p->buf,p->length);
102             }
103 
104         }
105     }
106 
107     close(fd);
108     close(tcp_socket);
109     close(con_socket);
110 
111 
112     return 0;
113 }
file_recv
  1 #include <stdio.h>
  2 #include <sys/socket.h>
  3 #include <sys/types.h>           /* See NOTES */
  4 #include <netinet/in.h>
  5 #include <netinet/ip.h> /* superset of previous */
  6 #include <arpa/inet.h>
  7 #include <stdlib.h>
  8 #include <string.h>
  9 #include <sys/stat.h>
 10 #include <fcntl.h>
 11 
 12 #include "file.h"
 13 
 14 
 15 int main(int argc, const char *argv[])
 16 {
 17     if(argc != 4)
 18     {
 19         fprintf(stderr,"please input port ip and filename!\n");
 20         exit(1);
 21     }
 22     
 23     //拼接路径
 24     char pathname[128];
 25     memset(pathname,0,sizeof(pathname));
 26     sprintf(pathname,"/home/xyx/teach/18072/net_tcp/file_2/%s",argv[3]);
 27 
 28     //open 
 29     int fd;
 30     fd = open(pathname,O_RDONLY);
 31     if(fd == -1)
 32     {
 33         perror("fail to open");
 34         exit(1);
 35     }
 36 
 37     node_t *p = malloc(sizeof(node_t));
 38 
 39     //socket
 40     int tcp_socket;
 41     tcp_socket = socket(AF_INET, SOCK_STREAM, 0);
 42     if(tcp_socket == -1)
 43     {
 44         perror("fail to socket");
 45         exit(1);
 46     }
 47     
 48     //服务器地址结构体
 49     struct sockaddr_in ser_addr;
 50 
 51     ser_addr.sin_family = AF_INET;
 52     ser_addr.sin_port = htons(atoi(argv[1]));
 53     ser_addr.sin_addr.s_addr = inet_addr(argv[2]);
 54 
 55     //connect
 56     if(-1 == connect(tcp_socket,(struct sockaddr*)&ser_addr,sizeof(ser_addr)))
 57     {
 58         perror("fail to connect");
 59         exit(1);
 60     }
 61     
 62     //发送文件名
 63     memset(p,0,sizeof(node_t));
 64     p->type = HQ_FILENAME;
 65     strcpy(p->buf,argv[3]);
 66     p->length = strlen(p->buf);
 67 
 68     send(tcp_socket,p,sizeof(node_t),0);    
 69 
 70     //发送文件内容
 71     int ret_read;
 72     while(1)
 73     {
 74         memset(p,0,sizeof(node_t));
 75         
 76         p->type = HQ_FILEDATA;
 77     
 78         ret_read = read(fd,p->buf,sizeof(p->buf));
 79         if(ret_read == -1)
 80         {
 81             perror("fail to read");
 82             exit(1);
 83         }
 84         else if(ret_read == 0)
 85         {
 86             break;
 87         }
 88         else
 89         {
 90             p->length = ret_read;
 91             //send 
 92             send(tcp_socket,p,sizeof(node_t),0);
 93         }
 94     }
 95 
 96     close(fd);
 97     close(tcp_socket);
 98 
 99     return 0;
100 }
file_send

 

TCP并发服务器: 多进程 僵尸进程务必解决!!
socket

bind

listen

while(1)
accept

fork

while(1)
recv

1.信号忽略

信号忽略
  1 #include <stdio.h>
  2 #include <sys/socket.h>
  3 #include <netinet/in.h>
  4 #include <sys/types.h>           /* See NOTES */
  5 #include <netinet/ip.h> /* superset of previous */
  6 #include <stdlib.h>
  7 #include <unistd.h>
  8 #include <arpa/inet.h>
  9 #include <string.h>
 10 #include <signal.h>
 11 
 12 int main(int argc, const char *argv[])
 13 {
 14     signal(SIGCHLD,SIG_IGN);
 15     char buf[128];
 16     pid_t pid;
 17     //socket
 18     int tcp_socket,con_socket;
 19     tcp_socket = socket(AF_INET, SOCK_STREAM, 0);
 20     if(tcp_socket == -1)
 21     {
 22         perror("fail to socket");
 23         exit(1);
 24     }
 25 
 26     int optval = 1;
 27     if(-1 == setsockopt(tcp_socket,SOL_SOCKET,SO_REUSEADDR,&optval,sizeof(optval)))
 28     {
 29         perror("fail to setsockopt");
 30         exit(1);
 31     }
 32 
 33     struct sockaddr_in ser_addr,cli_addr;
 34 
 35     ser_addr.sin_family = AF_INET;
 36     ser_addr.sin_port = htons(50000);
 37     ser_addr.sin_addr.s_addr = inet_addr("0.0.0.0");
 38 
 39     //bind
 40     if(-1 == bind(tcp_socket,(struct sockaddr*)&ser_addr,sizeof(ser_addr)))    
 41     {
 42         perror("fail to bind");
 43         exit(1);
 44     }
 45 
 46     //listen
 47     if(-1 == listen(tcp_socket,5))    
 48     {
 49         perror("fail to listen");
 50         exit(1);
 51     }
 52 
 53     socklen_t len = sizeof(cli_addr);
 54 
 55     while(1)
 56     {
 57         //accept
 58         con_socket = accept(tcp_socket,(struct sockaddr*)&cli_addr,&len);
 59         if(con_socket == -1)
 60         {
 61             perror("fail to accept");
 62             exit(1);
 63         }
 64 
 65         printf("%s %d is connecting!\n",inet_ntoa(cli_addr.sin_addr),ntohs(cli_addr.sin_port));
 66 
 67         //fork    
 68         pid = fork();
 69         if(pid < 0)
 70         {
 71             perror("fail to fork");
 72             exit(1);
 73         }
 74         else if(pid == 0)  //子进程  处理recv
 75         {
 76             close(tcp_socket);    
 77             while(1)
 78             {
 79                 memset(buf,0,sizeof(buf));
 80                 //recv
 81                 int ret_recv;
 82                 ret_recv = recv(con_socket,buf,sizeof(buf),0);
 83                 if(ret_recv == -1)
 84                 {
 85                     perror("fail to recv");
 86                     exit(1);
 87                 }
 88                 else if(ret_recv == 0) //数据传输完毕 退出!!
 89                 {
 90                     printf("%s %d is shutdown!\n",inet_ntoa(cli_addr.sin_addr),ntohs(cli_addr.sin_port));
 91                     close(con_socket);
 92                     exit(0);
 93                 }
 94                 else
 95                 {
 96                     printf("ip:%s port:%d say:%s!\n",inet_ntoa(cli_addr.sin_addr),ntohs(cli_addr.sin_port),buf);
 97                 }
 98 
 99             }
100 
101         }
102         else  //父建立连接 
103         {
104             //        wait(NULL); 不能用阻塞了父进程
105             close(con_socket);
106         }
107 
108 
109     }
110     return 0;
111 }

2.父子孙

  1 #include <stdio.h>
  2 #include <sys/socket.h>
  3 #include <netinet/in.h>
  4 #include <sys/types.h>           /* See NOTES */
  5 #include <netinet/ip.h> /* superset of previous */
  6 #include <stdlib.h>
  7 #include <unistd.h>
  8 #include <arpa/inet.h>
  9 #include <string.h>
 10 
 11 
 12 int main(int argc, const char *argv[])
 13 {
 14 
 15     char buf[128];
 16     pid_t pid1,pid2;
 17     //socket
 18     int tcp_socket,con_socket;
 19     tcp_socket = socket(AF_INET, SOCK_STREAM, 0);
 20     if(tcp_socket == -1)
 21     {
 22         perror("fail to socket");
 23         exit(1);
 24     }
 25 
 26     int optval = 1;
 27     if(-1 == setsockopt(tcp_socket,SOL_SOCKET,SO_REUSEADDR,&optval,sizeof(optval)))
 28     {
 29         perror("fail to setsockopt");
 30         exit(1);
 31     }
 32 
 33     struct sockaddr_in ser_addr,cli_addr;
 34 
 35     ser_addr.sin_family = AF_INET;
 36     ser_addr.sin_port = htons(50000);
 37     ser_addr.sin_addr.s_addr = inet_addr("0.0.0.0");
 38 
 39     //bind
 40     if(-1 == bind(tcp_socket,(struct sockaddr*)&ser_addr,sizeof(ser_addr)))    
 41     {
 42         perror("fail to bind");
 43         exit(1);
 44     }
 45 
 46     //listen
 47     if(-1 == listen(tcp_socket,5))    
 48     {
 49         perror("fail to listen");
 50         exit(1);
 51     }
 52 
 53     socklen_t len = sizeof(cli_addr);
 54 
 55     while(1)
 56     {
 57         //accept
 58         con_socket = accept(tcp_socket,(struct sockaddr*)&cli_addr,&len);
 59         if(con_socket == -1)
 60         {
 61             perror("fail to accept");
 62             exit(1);
 63         }
 64 
 65         printf("%s %d is connecting!\n",inet_ntoa(cli_addr.sin_addr),ntohs(cli_addr.sin_port));
 66 
 67         //fork    
 68         pid1 = fork();
 69         if(pid1 < 0)
 70         {
 71             perror("fail to fork1");
 72             exit(1);
 73         }
 74         else if(pid1 == 0)  //子进程 进行第二次fork产生孙进程
 75         {
 76             pid2 = fork();
 77             if(pid2 < 0)
 78             {
 79                 perror("fail to fork2");
 80                 exit(1);
 81             }
 82             else if(pid2 == 0) //孙进程
 83             {
 84                 close(tcp_socket);
 85                 while(1)
 86                 {
 87                     memset(buf,0,sizeof(buf));
 88                     //recv
 89                     int ret_recv;
 90                     ret_recv = recv(con_socket,buf,sizeof(buf),0);
 91                     if(ret_recv == -1)
 92                     {
 93                         perror("fail to recv");
 94                         exit(1);
 95                     }
 96                     else if(ret_recv == 0) //数据传输完毕 退出!!
 97                     {
 98                         printf("%s %d is shutdown!\n",inet_ntoa(cli_addr.sin_addr),ntohs(cli_addr.sin_port));
 99                         close(con_socket);
100                         exit(0);
101                     }
102                     else
103                     {
104                         printf("ip:%s port:%d say:%s!\n",inet_ntoa(cli_addr.sin_addr),ntohs(cli_addr.sin_port),buf);
105                     }
106 
107                 }
108             }
109             else //子进程  自杀
110             {
111                 exit(0);
112             }
113         }
114 
115 
116         else  //父建立连接 回收子进程
117         {
118             wait(NULL); //不能用阻塞了父进程
119             close(con_socket);
120         }
121 
122 
123     }
124     return 0;
125 }
父子孙

I/O模型:
阻塞

非阻塞
1.函数自带
recvfrom
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);
参数4:int flags是选项 填0默认阻塞状态 填MSG_DONTWAIT表示非阻塞
使用非阻塞选项时会出现错误 EAGAIN EWOULDBLOCK 这两个errno号在当前版本一致

 1 #include <stdio.h>
 2 #include <sys/types.h>           /* See NOTES */
 3 #include <sys/socket.h>
 4 #include <arpa/inet.h>
 5 #include <netinet/in.h>
 6 #include <netinet/ip.h> /* superset of previous */
 7 #include <stdlib.h>
 8 #include <strings.h>
 9 #include <unistd.h>
10 #include <errno.h>
11 
12 
13 int main(int argc, const char *argv[])
14 {
15     char buf[128];
16     //打开编程接口 socket
17     int udp_socket;
18     udp_socket = socket(AF_INET, SOCK_DGRAM, 0);
19     if(udp_socket == -1)
20     {
21         perror("fail to socket");
22         exit(1);
23     }
24 
25     //填充地址结构体
26     struct sockaddr_in ser_addr,cli_addr;
27 
28     ser_addr.sin_family = AF_INET;
29     ser_addr.sin_port = htons(50000); 
30     ser_addr.sin_addr.s_addr = inet_addr("192.168.2.192");
31 
32     //绑定ser ip和port  bind
33     if(-1 == bind(udp_socket,(struct sockaddr *)&ser_addr,sizeof(ser_addr)))
34     {
35         perror("fail to bind");
36         exit(1);
37     }
38 
39     socklen_t len = sizeof(cli_addr);
40 
41     while(1)
42     {
43         bzero(buf,sizeof(buf));
44         //recvfrom
45         if(-1 == recvfrom(udp_socket,buf,sizeof(buf),MSG_DONTWAIT,(struct sockaddr*)&cli_addr,&len))
46         {
47             if(errno != EAGAIN || errno != EWOULDBLOCK)
48             {
49                 perror("fail to recvfrom");
50                 exit(1);
51             }
52             else
53             {
54                 fprintf(stderr,"no data!\n");
55             }
56             sleep(1);
57         }
58         else
59         {        
60             printf("cli_ip:%s cli_port:%d recv:%s\n",inet_ntoa(cli_addr.sin_addr),ntohs(cli_addr.sin_port),buf);
61         }
62     }
63 
64     return 0;
65 }
不阻塞

2.fcntl 本质就是对文件描述符进行修改
int fcntl(int fd, int cmd, ... /* arg */ );
参数:
1.文件描述符
2.指令
对文件状态进行操作时使用的宏
F_GETFL 获取文件描述符状态和访问权限 arg忽略 使用后返回文件描述符的状态属性
F_SETFL 利用arg对文件描述符进行状态设置
3.可选参数arg 根据cmd看情况使用

man 2 open
创建旗 O_CREAT O_TRUNC O_EXCL
访问旗 O_RDONLY O_WRONLY O_RDWR
状态旗 O_NONBLOCK 非阻塞

 1 #include <stdio.h>
 2 #include <sys/types.h>           /* See NOTES */
 3 #include <sys/socket.h>
 4 #include <arpa/inet.h>
 5 #include <netinet/in.h>
 6 #include <netinet/ip.h> /* superset of previous */
 7 #include <stdlib.h>
 8 #include <strings.h>
 9 #include <unistd.h>
10 #include <fcntl.h>
11 #include <errno.h>
12 
13 int main(int argc, const char *argv[])
14 {
15     char buf[128];
16     //打开编程接口 socket
17     int udp_socket;
18     udp_socket = socket(AF_INET, SOCK_DGRAM, 0);
19     if(udp_socket == -1)
20     {
21         perror("fail to socket");
22         exit(1);
23     }
24 
25     //填充地址结构体
26     struct sockaddr_in ser_addr,cli_addr;
27 
28     ser_addr.sin_family = AF_INET;
29     ser_addr.sin_port = htons(50000); 
30     ser_addr.sin_addr.s_addr = inet_addr("192.168.2.192");
31 
32     //绑定ser ip和port  bind
33     if(-1 == bind(udp_socket,(struct sockaddr *)&ser_addr,sizeof(ser_addr)))
34     {
35         perror("fail to bind");
36         exit(1);
37     }
38 
39     socklen_t len = sizeof(cli_addr);
40 
41     int flag,flag1;
42     //1.获取文件描述符状态属性
43     flag = fcntl(udp_socket,F_GETFL);
44 
45     //2.添加O_NONBLOCK属性
46     flag = flag | O_NONBLOCK;
47 
48     //将flag设置回去
49     fcntl(udp_socket,F_SETFL,flag);
50 
51     
52     flag1 = fcntl(0,F_GETFL);
53 
54     flag1 |= O_NONBLOCK;
55 
56     fcntl(0,F_SETFL,flag1);
57 
58     while(1)
59     {
60         bzero(buf,sizeof(buf));
61 
62         if(NULL == fgets(buf,sizeof(buf),stdin))
63         {
64             printf("fgets:%s\n",buf);
65         }
66 
67         //recvfrom
68         if(-1 == recvfrom(udp_socket,buf,sizeof(buf),0,(struct sockaddr*)&cli_addr,&len))
69         {
70             if(errno != EAGAIN || errno != EWOULDBLOCK)
71             {
72                 perror("fail to recvfrom");
73                 exit(1);
74             }
75             else
76             {
77                 fprintf(stderr,"no data!\n");
78             }
79             sleep(1);
80         }
81         else    
82         {
83             printf("cli_ip:%s cli_port:%d recv:%s\n",inet_ntoa(cli_addr.sin_addr),ntohs(cli_addr.sin_port),buf);
84 
85         }
86     }
87 
88     return 0;
89 }
fcntl

3.利用open函数 一般不用

异步IO 由内核监视IO资源,当资源到达时发送SIGIO的信号给执行进程,执行对应操作
1.开启异步功能
fcntl F_GETFL F_SETFL
O_ASYNC man 2 open 状态旗 异步IO

2.将当前进程PID交给内核
fcntl F_SETOWN 需要arg参数的支持

3.捕获SIGIO信号,执行对应操作
signal

 1 #include <stdio.h>
 2 #include <sys/types.h>           /* See NOTES */
 3 #include <sys/socket.h>
 4 #include <arpa/inet.h>
 5 #include <netinet/in.h>
 6 #include <unistd.h>
 7 #include <fcntl.h>
 8 #include <netinet/ip.h> /* superset of previous */
 9 #include <stdlib.h>
10 #include <strings.h>
11 #include <signal.h>
12 
13 char buf[128];
14 int udp_socket;
15 struct sockaddr_in ser_addr,cli_addr;
16 socklen_t len = sizeof(cli_addr);
17 void handler(int signum)
18 {
19     bzero(buf,sizeof(buf));
20     //recvfrom
21     if(-1 == recvfrom(udp_socket,buf,sizeof(buf),0,(struct sockaddr*)&cli_addr,&len))
22     {
23         perror("fail to recvfrom");
24         exit(1);
25     }
26 
27     printf("cli_ip:%s cli_port:%d recv:%s\n",inet_ntoa(cli_addr.sin_addr),ntohs(cli_addr.sin_port),buf);
28 
29 }
30 
31 
32 
33 int main(int argc, const char *argv[])
34 {
35 
36     signal(SIGIO,handler);
37     //打开编程接口 socket
38     udp_socket = socket(AF_INET, SOCK_DGRAM, 0);
39     if(udp_socket == -1)
40     {
41         perror("fail to socket");
42         exit(1);
43     }
44 
45     //填充地址结构体
46 
47     ser_addr.sin_family = AF_INET;
48     ser_addr.sin_port = htons(50000); 
49     ser_addr.sin_addr.s_addr = inet_addr("192.168.2.192");
50 
51     //绑定ser ip和port  bind
52     if(-1 == bind(udp_socket,(struct sockaddr *)&ser_addr,sizeof(ser_addr)))
53     {
54         perror("fail to bind");
55         exit(1);
56     }
57 
58 
59     //开启异步功能
60     int flag;
61     flag = fcntl(udp_socket,F_GETFL);
62 
63     flag |= O_ASYNC;
64 
65     fcntl(udp_socket,F_SETFL,flag);
66 
67     //将当前进程PID交给内核
68     fcntl(udp_socket,F_SETOWN,getpid());    
69 
70     while(1)
71     {
72         sleep(2);
73         printf("no data!\n");
74     }
75 
76     close(udp_socket);
77     return 0;
78 }
开启异步

 

多路复用 : 在网络中实现一个进程处理多路IO操作
select
int select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *timeout);
参数:1.最大文件描述符个数 2.读资源表 3.写资源表(填NULL) 4.异常资源表(填NULL)
5.超时结构体(设置阻塞的时间)
struct timeval {
long tv_sec; /* seconds */
long tv_usec; /* microseconds */
};
返回值:成功返回就绪的文件描述符个数 2.失败返回-1 3.0代表超时
功能:1.讲关心的文件描述符传递给内核 2.阻塞等待关心的文件描述符就绪 3.就绪的文件描述符返回在参数中

select编程思考线路:
1.制作表单
表单的形式:fd_set
对表单操作的宏函数
void FD_CLR(int fd, fd_set *set); //从表单中清楚指定文件描述符(不关心)
int FD_ISSET(int fd, fd_set *set); //校验文件描述符是否还在表内存在 1存在 0不存在
void FD_SET(int fd, fd_set *set); //往表单内设置成员(关系内的文件描述符)
void FD_ZERO(fd_set *set); //清0表单
2.将表单传递给内核 select传递
3.内核轮询
4.当有资源就绪时,返回进程 select接收
5.遍历表格,执行对应操作 

  1 #include <stdio.h>
  2 #include <sys/socket.h>
  3 #include <sys/types.h>           /* See NOTES */
  4 #include <sys/select.h>
  5 #include <netinet/in.h>
  6 #include <unistd.h>
  7 #include <netinet/ip.h> /* superset of previous */
  8 #include <sys/time.h>
  9 #include <stdlib.h>
 10 #include <arpa/inet.h>
 11 #include <string.h>
 12 
 13 int main(int argc, const char *argv[])
 14 {
 15     char buf[128];
 16     int recv_ret;
 17     //socket  使用流式套接字
 18     int tcp_socket,con_socket;
 19     tcp_socket = socket(AF_INET, SOCK_STREAM, 0);
 20     if(tcp_socket == -1)
 21     {
 22         perror("fail to socket");
 23         exit(1);
 24     }
 25 
 26     int optval = 1;
 27     //setsockopt  设置套接字属性
 28     if(-1 == setsockopt(tcp_socket,SOL_SOCKET,SO_REUSEADDR,&optval,sizeof(optval)))
 29     {
 30         perror("fail to setsockopt");
 31         exit(1);
 32     }
 33 
 34     //struct sockaddr_in
 35     struct sockaddr_in ser_addr,cli_addr;
 36 
 37     ser_addr.sin_family = AF_INET;
 38     ser_addr.sin_port = htons(50000);
 39     ser_addr.sin_addr.s_addr = inet_addr("0.0.0.0");
 40     //0.0.0.0 本机ip地址自动适配
 41 
 42     //bind   服务器ip和port
 43     if(-1 == bind(tcp_socket,(struct sockaddr*)&ser_addr,sizeof(ser_addr)))
 44     {
 45         perror("fail to bind");
 46         exit(1);
 47     }
 48 
 49     //listen  将socket变成监听模式
 50     if(-1 == listen(tcp_socket,5))
 51     {
 52         perror("fail to listen");
 53         exit(1);
 54     }
 55 
 56     socklen_t len = sizeof(cli_addr);
 57 
 58     //
 59     fd_set global,current;
 60 
 61     //添加成员到全局表中(0,监听套接字)
 62     FD_ZERO(&global);
 63     FD_SET(0,&global);
 64     FD_SET(tcp_socket,&global);  
 65 
 66     struct timeval tv;
 67     int ret_select;
 68     int maxfd = tcp_socket; //maxfd是指当前最大的文件描述符的值
 69 
 70     while(1)
 71     {
 72         FD_ZERO(&current);
 73         current = global;
 74 
 75         tv.tv_sec = 3;
 76         tv.tv_usec = 0;
 77         //select
 78         ret_select = select(maxfd+1,&current,NULL,NULL,&tv);
 79         if(ret_select == -1)
 80         {
 81             perror("fail to select");
 82             exit(1);
 83         }
 84         else if(ret_select == 0)
 85         {
 86             printf("timeout!\n");
 87             continue;
 88         }
 89         else
 90         {
 91             if(FD_ISSET(0,&current))
 92             {
 93                 memset(buf,0,sizeof(buf));
 94                 fgets(buf,sizeof(buf),stdin);
 95                 printf("fgets:%s\n",buf);
 96             }
 97             if(FD_ISSET(tcp_socket,&current))
 98             {
 99                 memset(&cli_addr,0,len);
100                 //accept 建立连接
101                 con_socket = accept(tcp_socket,(struct sockaddr*)&cli_addr,&len);
102                 if(con_socket == -1)
103                 {
104                     perror("fail to accept");
105                     exit(1);
106                 }
107 
108                 printf("%s %d is connnecting!\n",inet_ntoa(cli_addr.sin_addr),ntohs(cli_addr.sin_port));
109                 printf("con_socket:%d is add!\n",con_socket);    
110                 //添加新的文件描述符到global表中
111                 FD_SET(con_socket,&global);
112 
113                 //更新最大文件描述符
114                 if(maxfd < con_socket)
115                 {
116                     maxfd = con_socket;
117                 }
118 
119             }
120             int i;
121             //循环判断con_socket们中就绪的成员
122             for(i = 3;i <= maxfd;i++)
123             {
124                 if(i == tcp_socket)
125                 {
126                     continue;
127                 }
128 
129                 if(FD_ISSET(i,&current))
130                 {
131                     memset(buf,0,sizeof(buf));
132                     //recv 接收消息
133                     recv_ret = recv(i,buf,sizeof(buf),0);
134                     if(recv_ret < 0)
135                     {
136                         perror("fail to recv");
137                         exit(1);
138                     }
139                     else if(recv_ret == 0) //数据接收完毕  
140                     {
141                         printf("con_socket:%d is del!\n",i);
142                         close(i);
143                         FD_CLR(i,&global);
144                         //优化代码
145                         if(maxfd == i)
146                         {
147                             while(--maxfd)
148                             {
149                                 if(FD_ISSET(maxfd,&global))
150                                     break;
151                             }
152                         }
153                     }
154                     else
155                     {
156                         printf("recv:%s\n",buf);
157                     }
158 
159                 }
160 
161             }
162 
163 
164 
165         }
166     }
167 
168 
169     return 0;
170 }
select

 

epoll
epoll_create:创建epoll事件 并申请表格大小
int epoll_create(int size);
返回值:成功返回epoll事件的文件描述符 失败返回-1,并设置errno号

epoll_ctl 类似select中的FD_SET FD_CLR
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
参数:
1.epoll_create返回的文件描述符
2. 选项 添加或删除关心的文件描述符 EPOLL_CTL_ADD添加 EPOLL_CTL_DEL删除
3.文件描述符 关心的文件描述符
4.epoll事件结构体
typedef union epoll_data {
void *ptr;
int fd;
uint32_t u32;
uint64_t u64;
} epoll_data_t;

struct epoll_event {
uint32_t events; /* Epoll events */ EPOLLIN 读资源 EPOLLOUT 写资源
epoll_data_t data; /* User data variable */
};

epoll_wait 阻塞等待一个或者多个资源就绪
int epoll_wait(int epfd, struct epoll_event *events,int maxevents, int timeout);
参数:1.epoll_create返回的文件描述符 2.struct epoll_event 的数组 (用于接收来自内核的就绪的成员)
3.数组大小 4.超时 -1代表阻塞
返回值:成功返回就绪的文件描述符个数,失败返回-1,0代表没有成员就绪

  1 #include <stdio.h>
  2 #include <sys/socket.h>
  3 #include <sys/types.h>           /* See NOTES */
  4 #include <netinet/in.h>
  5 #include <netinet/ip.h> /* superset of previous */
  6 #include <stdlib.h>
  7 #include <sys/epoll.h>
  8 #include <arpa/inet.h>
  9 #include <string.h>
 10 
 11 int main(int argc, const char *argv[])
 12 {
 13     char buf[128];
 14     int recv_ret;
 15     //socket  使用流式套接字
 16     int tcp_socket,con_socket;
 17     tcp_socket = socket(AF_INET, SOCK_STREAM, 0);
 18     if(tcp_socket == -1)
 19     {
 20         perror("fail to socket");
 21         exit(1);
 22     }
 23 
 24     int optval = 1;
 25     //setsockopt  设置套接字属性
 26     if(-1 == setsockopt(tcp_socket,SOL_SOCKET,SO_REUSEADDR,&optval,sizeof(optval)))
 27     {
 28         perror("fail to setsockopt");
 29         exit(1);
 30     }
 31 
 32     //struct sockaddr_in
 33     struct sockaddr_in ser_addr,cli_addr;
 34 
 35     ser_addr.sin_family = AF_INET;
 36     ser_addr.sin_port = htons(50000);
 37     ser_addr.sin_addr.s_addr = inet_addr("0.0.0.0");
 38     //0.0.0.0 本机ip地址自动适配
 39 
 40     //bind   服务器ip和port
 41     if(-1 == bind(tcp_socket,(struct sockaddr*)&ser_addr,sizeof(ser_addr)))
 42     {
 43         perror("fail to bind");
 44         exit(1);
 45     }
 46 
 47     //listen  将socket变成监听模式
 48     if(-1 == listen(tcp_socket,5))
 49     {
 50         perror("fail to listen");
 51         exit(1);
 52     }
 53 
 54     socklen_t len = sizeof(cli_addr);
 55 
 56     //epoll_create 
 57     int epoll_fd;
 58     epoll_fd = epoll_create(50);
 59     if(epoll_fd == -1)
 60     {
 61         perror("fail to epoll_create");
 62         exit(1);
 63     }
 64 
 65     //epoll_ctl  添加0和tcp_socket
 66     struct epoll_event ev;
 67     ev.events = EPOLLIN;
 68     ev.data.fd = 0;
 69 
 70     if(-1 == epoll_ctl(epoll_fd,EPOLL_CTL_ADD,0,&ev))
 71     {
 72         perror("fail to epoll_ctl 0");
 73         exit(1);
 74     }
 75 
 76     ev.events = EPOLLIN;
 77     ev.data.fd = tcp_socket;
 78 
 79     if(-1 == epoll_ctl(epoll_fd,EPOLL_CTL_ADD,tcp_socket,&ev))
 80     {
 81         perror("fail to epoll_ctl tcp_socket");
 82         exit(1);
 83     }
 84 
 85     int ret_epoll;
 86     struct epoll_event array[50];   
 87 
 88     while(1)
 89     {
 90         ret_epoll = epoll_wait(epoll_fd,array,50,-1);
 91         if(ret_epoll == -1)
 92         {
 93             perror("fail to epoll_wait");
 94             exit(1);
 95         }
 96 
 97         int i;
 98         for(i = 0;i < ret_epoll;i++)
 99         {
100             if(array[i].data.fd == 0)
101             {
102                 memset(buf,0,sizeof(buf));
103                 fgets(buf,sizeof(buf),stdin);
104                 printf("fgets:%s\n",buf);
105             }
106             else if(array[i].data.fd == tcp_socket)
107             {
108                 //accept 建立连接
109                 con_socket = accept(tcp_socket,(struct sockaddr*)&cli_addr,&len);
110                 if(con_socket == -1)
111                 {
112                     perror("fail to accept");
113                     exit(1);
114                 }
115 
116                 printf("%s %d is connnecting!\n",inet_ntoa(cli_addr.sin_addr),ntohs(cli_addr.sin_port));
117                 printf("con_socket:%d is add!\n",con_socket);        
118 
119                 ev.events = EPOLLIN;
120                 ev.data.fd = con_socket;
121 
122                 if(-1 == epoll_ctl(epoll_fd,EPOLL_CTL_ADD,con_socket,&ev))
123                 {
124                     perror("fail to epoll_ctl con_socket");
125                     exit(1);
126                 }
127 
128 
129             }
130             else
131             {
132                 memset(buf,0,sizeof(buf));
133                 //recv 接收消息
134                 recv_ret = recv(array[i].data.fd,buf,sizeof(buf),0);
135                 if(recv_ret < 0)
136                 {
137                     perror("fail to recv");
138                     exit(1);
139                 }
140                 else if(recv_ret == 0) //数据接收完毕  
141                 {
142                     printf("con_socket:%d is del!\n",array[i].data.fd);
143                     //先删后关
144                     if(-1 == epoll_ctl(epoll_fd,EPOLL_CTL_DEL,array[i].data.fd,NULL))
145                     {
146                         perror("fail to epoll_ctl del");
147                         exit(1);
148                     }
149                     close(array[i].data.fd);
150                 }
151                 else
152                 {
153                     printf("recv:%s\n",buf);
154                 }
155             }
156         }
157 
158     }
159     return 0;
160 }
epooll

 

Sqlite3

安装:
sudo dpkg -i *.deb

数据库基本命令:
sqlite3 数据库名.db
.quit 退出数据库
.database 查看数据库文件信息
.table 查看数据库中的表单
.schema 查看表单属性

SQL语句
创建表单:
create table 表单名(列1 列1属性,列2 列2属性,列3 列3属性);
例如:
create table stu(name char[20],id int,sex char[10],score int);

增加数据:
insert into 表单名 values(值1,值2,值3);
例如:
insert into stu values("xm",1,"man",90);
insert into stu values("xh",2," ",80); 省略了一列

查找数据:
select 列名 from 表单名 where + 条件;
例如:
select name from stu where score>=80; 查找分数>=80的人名
select name from stu where score>=80 and score<=90;
全表查询:select * from 表单名;

删除数据:
delete from 表单名 where + 条件;
例如:
delete from stu where name=="xm";

修改数据:
update 表单名 set 列名 = 新的值 where + 条件;
例如:
update stu set sex="girl" where id==2;

删除表单:
drop table 表单名;

sqlite官网
www.sqlite.org

sqlite3的C接口:
1.添加头文件#include<sqlite3.h>
2.编译时链接数据库 -lsqlite3
sqlite3_open 打开数据库文件
int sqlite3_open(const char *filename, /* Database filename (UTF-8) */sqlite3 **ppDb /* OUT: SQLite db handle */);
参数:1.数据库文件名 2.打开数据库成功时返回sqlite3 *类型的指针用于对数据库文件操作(类似FILE*)
返回值:成功返回SQLITE_OK

sqlite3_exec 通过sql语句操作数据库文件
int sqlite3_exec(sqlite3*, /* An open database */const char *sql, /* SQL to be evaluated */int (*callback)(void*,int,char**,char**), /* Callback function */
void *, /* 1st argument to callback */char **errmsg /* Error msg written here */);
参数:1.sqlite3_open打开时返回的sqlite3*的指针;

2.指定的sql语句;

3.callback函数的函数指针 不使用填NULL int (void*,int,char**,char**); 获取数据时通过callback获取;

4.callback函数传参使用 (双向的) 填NULL不使用
5.返回的时错误信息的首地址
返回值:成功返回SQLITE_OK,失败通过参数errmsg返回 记得使用sqlite3_free释放空间

callback:根据查询结果调用,一行数据执行一次,没有数据不执行,按类char *型数组返回
int callback(void *,int,char **,char **);
参数:
1.void * 双向传参 callback->main main(sqlite3_exec)->callback
2.获取到数据的个数
3.该数据存放的数组首地址
4.每一列名字存放的数组首地址

sqlite3_close 关闭数据库文件
int sqlite3_close(sqlite3*);
参数:1.sqlite3_open打开时返回的sqlite3 *的指针

  1 #include <stdio.h>
  2 #include <sqlite3.h>
  3 #include <stdlib.h>
  4 #include <string.h>
  5 
  6 int callback1(void *s,int count,char **colval,char **colname);
  7 int callback2(void *s,int count,char **colval,char **colname);
  8 
  9 int main(int argc, const char *argv[])
 10 {
 11     //sqlite3_open
 12     sqlite3 * db;
 13     char *errmsg;
 14     int ret;
 15     ret = sqlite3_open("./test.db",&db);
 16     if(ret != SQLITE_OK)
 17     {
 18         fprintf(stderr,"fail to open db!\n");
 19         exit(1);
 20     }
 21     
 22     //对数据库操作
 23     //sql语句和sqlite3_exec
 24     char *sql = "create table stu(name char[10],sex char[10],score int)";
 25 
 26     ret = sqlite3_exec(db,sql,NULL,NULL,&errmsg);
 27     if(ret != SQLITE_OK)
 28     {
 29         fprintf(stderr,"fail to sqlite3_exec:%s\n",errmsg);
 30         sqlite3_free(errmsg);
 31         exit(1);
 32     }
 33 
 34     sql = "insert into stu values('xiaom','boy',90)";
 35     
 36     ret = sqlite3_exec(db,sql,NULL,NULL,&errmsg);
 37     if(ret != SQLITE_OK)
 38     {
 39         fprintf(stderr,"fail to sqlite3_exec:%s\n",errmsg);
 40         sqlite3_free(errmsg);
 41         exit(1);
 42     }
 43 
 44     sql = "insert into stu values('xiaoh','girl',80)";
 45     
 46     ret = sqlite3_exec(db,sql,NULL,NULL,&errmsg);
 47     if(ret != SQLITE_OK)
 48     {
 49         fprintf(stderr,"fail to sqlite3_exec:%s\n",errmsg);
 50         sqlite3_free(errmsg);
 51         exit(1);
 52     }
 53 
 54     //callback1
 55     sql = "select * from stu";
 56     char *s1 = "heiheihei";
 57 
 58     ret = sqlite3_exec(db,sql,callback1,s1,&errmsg);
 59     if(ret != SQLITE_OK)
 60     {
 61         fprintf(stderr,"fail to sqlite3_exec:%s\n",errmsg);
 62         sqlite3_free(errmsg);
 63         exit(1);
 64     }
 65 
 66     //callback2
 67     char recv[20];
 68     ret = sqlite3_exec(db,sql,callback2,recv,&errmsg);
 69     if(ret != SQLITE_OK)
 70     {
 71         fprintf(stderr,"fail to sqlite3_exec:%s\n",errmsg);
 72         sqlite3_free(errmsg);
 73         exit(1);
 74     }
 75 
 76     printf("recv:%s\n",recv);
 77 
 78     //sqlite3_close
 79     sqlite3_close(db);
 80     return 0;
 81 }
 82 
 83 int callback1(void *s,int count,char **colval,char **colname)
 84 {
 85     if(s != NULL)
 86     {
 87         printf("callback1:%s\n",(char *)s);
 88     }
 89     
 90     int i;
 91     for(i = 0;i < count;i++)
 92     {
 93         printf("%s|%s\n",colname[i],colval[i]);
 94     }
 95     printf("\n");
 96 
 97     return 0;
 98 
 99 }
100 
101 
102 int callback2(void *s,int count,char **colval,char **colname)
103 {
104     int i;
105     for(i = 0;i < count;i++)
106     {
107         printf("%s|",colval[i]);
108     }
109     printf("\n");
110 
111     if(s != NULL)
112     {
113         strcpy((char *)s,"heiheihei2");
114     }
115 
116     return 0;
117 }
sqlite3_test

 

posted @ 2018-08-30 14:13  向往的生活ing  阅读(325)  评论(0编辑  收藏  举报