Linux 系统应用编程——网络编程(socket编程)

二、网络编程基础

1、套接字概述

       套接字就是网络编程的ID。网络通信,归根到底还是进程间的通信(不同计算机上的进程间的通信)。在网络中,每一个节点(计算机或路由器)都有一个网络地址,也就是IP地址,两个进程通信时,首先要确定各自所在网络节点的网络地址。但是,网络地址只能确定进程所在的计算机,而一台计算机上很可能同时运行着多个进程,所以仅凭网络地址还不能确定到底是和网络中哪一个进程通信,因此套接口中还需要有其他的信息,也就是端口号(port)。在一台计算机中,一个端口号一次只能分配给一个进程,也就是说,在一台计算机中,端口号和进程之间是一一对应的关系。所以,使用端口号和网络地址的组合就能唯一确定整个网络中的一个网络进程。

      把网络地址和端口号信息放在一个结构体中,也就是套接口地址结构,大多数的套接口函数都需要一个指向套接口地址结构的指针作为参数,并以此来传递地址信息。每个协议族都定义了它自己的套接口地址结构,套接字地址结构都以"sockaddr_” 开头,并以每个协议族名中两个字母作为结尾。

     下面是socket所在位置:

可以看到套接口有3种类型:

1)流式套接字(SOCK_STREAM)

      流式套接字提供可靠的、面向连接的通信刘,保证数据传输的可靠性和按序收发。TCP通信使用的就是流式套接字。

2)数据包套接字(SOCK_DGRAM)

      数据报套接字实现了一种不可靠、无连接的服务。数据通过相互独立的报文进行传输,是无序的,并且不保证可靠的传输。UDP通信使用的就是数据报套接字。

3)原始套接字(SOCK_RAW)

     原始套接字允许对底层协议(如IP或ICMP)进行直接访问,它功能强大但使用较为不便,主要用于一些协议的开发。

 

2、端口号

      这里的端口号是逻辑意义上的端口,一般是指TCP/IP 协议中的端口,端口号的范围为0~65535,比如用于浏览网页服务(HTTP协议)的80端口,用于FTP服务的21端口等。其中, 0 到1023 一般被系统程序所使用。

     那么TCP/IP协议中的端口指的是什么呢?举个例子,如果IP地址唯一指定了地球上某个地理位置的一间房子,端口号就是出入这间房子的门,只不过这个房子的门有65536个之多,端口是通过端口号来标记的,端口号是一个16位的整数,范围是从0~65535。

    端口号只具有本地意义,即端口号只是为了标识本地计算机上的各个进程。在互联网中不同计算机的相同端口号是没有联系的。16bit 的端口号可允许有64K个端口号,这个数目对一个计算机来说是足够用的。

 

3、IP地址

1)IP地址的作用

       IP地址用来表示网络中的一台主机。准确的说,IP地址是一台主机到一个网络的一个连接,因为现在一个主机中会有多个网卡。

      一个IP地址包含两部分:网络号和主机号。其中,网络号和主机号根据子网掩码来区分。简单的说,有了源IP 和目标 IP,数据包就能在不同主机之间传输。

2)IP地址格式转换

      IP地址有两种不同格式:十进制点分形式和32位二进制形式。前者是用户熟悉的形式,而后者则是网络传输中IP地址的存储方式。

      这里主要介绍IPV4地址转换函数,主要有 inet_addr() 、inet_aton() 、inet_ntoa() 。前两者的功能都是将字符串转换成32位网络字节序二进制值,第三个将32位网络字节序二进制地址转换成点分十进制的字符串。

inet_addr() 函数语法如下:

所需头文件#include <arpa/inet.h>
函数原型int  inet_addr(const char *strptr);
参数

strptr :要转换的IP地址字符串

函数返回值

成功:32位二进制IP地址(网络字节序)

出错:-1

inet_aton() 函数语法如下:

所需头文件#include <arpa/inet.h>
函数原型int  inet_aton(int family, const char *src , void *drt);
参数

family   AF_INET:IPV4协议

             AF_INET6:IPV6协议

src:要转换的IP地址字符串

函数返回值

成功:32位二进制IP地址(网络字节序)

出错:-1

inet_ntoa() 函数语法如下:

所需头文件#include <arpa/inet.h>
函数原型int  inet_ntoa(int family, const char *src , void *dst, size_t len);
参数

family   AF_INET:IPV4协议

             AF_INET6:IPV6协议

src:要转换的二进制IP地址;
dst:存放十进制地址字符串的缓冲区;
len:缓冲区的长度

函数返回值

成功:返回dst

出错:NULL

 

4、字节序

      字节序又称为主机字节序 Host Byte Order,HBO,是指计算机中多字节整型数据的存储方式。字节序有两种:大端(高位字节存储在低位地址,低位字节存储在高位地址)和小端(和大端序相反,PC通常采用小端模式)。

      为什么需要字节序?在网络通信中,发送方和接收方有可能使用不同的字节序;


为了保证数据接受后能被正确的解析处理,统一规定:数据以高位字节优先顺序在网络上传输。因此数据在发送前和接收后都需要在主机字节序和网络字节序之间转换。



1)函数说明

      字节序转换涉及4个函数:htons() 、ntohs() 、htonl() 和 ntohl() 。这里的 h 代表 host , n 代表 network , s 代表 short , l 代表 long 。通常 16bit 的IP端口号用前两个函数处理,而 IP 地址用后两个函数来转换。调用这些函数只是使其得到相应的字节序,用户不需要知道该系统的主机字节序和网络字节序是否真的相等。如果两个相同不需要转换的话,该系统的这些函数会定义成空宏。

2)函数格式

所需头文件#include <netinet/in.h>
函数原型unit16_t htons(unit 16_t hostshort);
unit32_t htonl(unit 32_t hostlong);
unit16_t ntohs(unit 16_t netshort);
unit32_t ntohl(unit 32_t netlong);
函数传入值hostshort:主机字节序的16bit 数据
hostlong :主机字节序的32t 数据
netshort  :网络字节序的16bit 数据
netlong:网络字节序的32bitt 数据
函数返回值成功:返回转换字节序后的数值
出错:-1

5、TCP编程

函数说明

socket()编程的基本函数有socket() 、bind()、listen()、accept()、send()、sendto()、recv()以及recvfrom()等。下面先简单介绍上述函数的功能,再结合流程图具体说明

1)socket() :该函数用于创建一个套接字,同时指定协议和类型。

2)bind()     :该函数将保存在相应地址结构中的地址信息与套接字进行绑定。它主要用于服务器端,客户端创建的套接字可以不绑定地址。

3)listen()   :在服务端程序成功建立套接字并与地址进行绑定以后,通过调用listen() 函数将TCP连接后,该函数会返回一个新的已连接套接字。

5)connect():客户端通过该函数向服务器端的监听套接字发送连接请求。

6)send() 和 recv():这两个函数通常在TCP通信过程中用于发送和接收数据,也可用于UDP中。

7)sendto()和recvfrom() :这两个函数一般在UDP通信过程中用于发送和接受数据。当用于TCP时,后面的几个与地址有关的参数不起作用,函数作用等同于 send() 和 recv()


服务器端和客户端使用TCP的流程如下:



可以看到通信工作的大致流程如下:

1)服务器先用socket() 函数来建立一个套接口,用这个套接口完成通信的监听及数据的收发;

2)服务器用bind() 函数来绑定一个端口号和IP地址,使套接口与制定的端口号和IP地址相关联;

3)服务器调用listen()函数,使服务器的这个端口和IP处于监听状态,等待网络中某一客户机的连接请求。

4)客户机调用socket()函数建立一个套接口,设定远程IP和端口。

5)客户机调用 connect() 函数链接远程计算机指定的端口。

6)服务器调用 accept() 函数来接受远程计算机的连接请求,建立起与客户机之间的通信连接。

7)建立连接以后,客户机用write() 函数 (或send()函数)向socket() 中写入数据,也可以用 read() 函数(或recv()函数)读取服务器发送来的数据。

8)服务器用 read()函数(或recv()函数)读取客户机发送来的数据,也可以用 write() 函数(或send()函数)来发送数据。

9)完成通信以后,使用close()函数关闭socket 连接。


函数格式:

1)创建套接口 socket() 函数

其语法要点

所需头文件#include <sys/socket.h>
函数原型 int socket(int family, int type,int protocol);
函数传入值family:协议族
type:套接字类型
protocol:0(原始套接字除外)
函数返回值成功:非负套接字描述符
出错:-1

参数family 指明协议族,取值如:

AF_INET:IPv4协议

AF_INET6:IPv6协议

AF_LOCAL:UNIX域协议

AF_ROUTE:路由套接字

AF_KEY:密钥套接字

这里“AF”代表“Adress Family”(地址族)

types指明通信字节流类型,其取值如:

SOCK_STREAM:流式套接字(TCP方式)

SOCK_DGRAM:数据包套接字(UDP方式)

SOCK_RAM:原始套接字


2)绑定端口 bind()函数

     用socket() 函数创建一个套接口后,需要使用bind 函数在这个套接口上绑定一个指定的端口号和IP地址。bind函数原型如下:

所需头文件#include <sys/socket.h>
函数原型 int bind(int sockfd, struct sockaddr *my_addr, int addrlen);
函数传入值sockfd:套接字描述符
my_addr:绑定的地址
addrlen:地址长度
函数返回值成功:0
出错:-1

这里my_addr是IPv4地址,IPv4 套接口地址数据结构以socketaddr_in 命名,定义在 <netinet/in.h>头文件中,形式如下:

[cpp] view plaincopy
在CODE上查看代码片派生到我的代码片
  1. struct sockaddr_in   
  2.   
  3. sa_family_t    sin_family; /* address family: AF_INET */  
  4. in_port_t      sin_port;   /* port in network byte order */  
  5. struct in_addr sin_addr;   /* internet address */  
  6. ;  

sin_famliy 为套接字结构协议族,如IPv4为AF_INET;

sin_port  是16位 TCP或UDP端口号,网络字节顺序;

结构体成员in_addr也是一个结构体,定义如下:

[cpp] view plaincopy
在CODE上查看代码片派生到我的代码片
  1. struct in_addr  
  2. {  
  3.     uint32_t s_addr;     /* address in network byte order */  
  4. };  
这里s_addr为32位IPv地址,网络字节顺序; 本地地址可以用INADDR_ANY;

字节排序函数上面已经介绍,下面看一个实例:

[cpp] view plaincopy
在CODE上查看代码片派生到我的代码片
  1. #include <stdio.h>  
  2. #include <string.h>  
  3. #include <stdlib.h>  
  4. #include <sys/types.h>  
  5. #include <sys/socket.h>  
  6. #include <netinet/in.h>  
  7. #include <arpa/inet.h>  
  8. #include <unistd.h>  
  9. #define PORT 2345  
  10.   
  11. int main()  
  12. {  
  13.     int sockfd;  
  14.     struct sockaddr_in addr;  
  15.     int addr_len = sizeof(struct sockaddr_in);  
  16.   
  17.     if((sockfd = socket(AF_INET,SOCK_STREAM,0)) < 0)  
  18.     {  
  19.         perror("socket fail");  
  20.         exit(-1);  
  21.     }  
  22.     else  
  23.     {  
  24.         printf("socket created successfully!\nsocket id is %d\n",sockfd);  
  25.     }  
  26.   
  27.     memset(&addr,0,addr_len);  
  28.     addr.sin_family = AF_INET;  
  29.     addr.sin_port = htons(PORT);  
  30.     addr.sin_addr.s_addr = htonl(INADDR_ANY);  
  31.   
  32.     if(bind(sockfd,(struct sockaddr *)(&addr),addr_len) < 0)  
  33.     {  
  34.         perror("bind error");  
  35.         exit(-1);  
  36.     }  
  37.     else  
  38.     {  
  39.         printf("bind port successfully!\nlocal port:%d\n",PORT);  
  40.     }  
  41.   
  42.     return 0;  
  43. }  
执行结果如下:
[cpp] view plaincopy
在CODE上查看代码片派生到我的代码片
  1. fs@ubuntu:~/qiang/net$ ./socket   
  2. socket created successfully!  
  3. socket id is 3  
  4. bind port successfully!  
  5. local port:2345  
  6. fs@ubuntu:~/qiang/net$   


3)等待监听函数

      所谓监听,指的是socket 的端口一直处于等待的状态,监听网络中的所有客户机,耐心等待某一客户机发送请求。如果客户端有连接请求,端口就会接受这个连接。listen 函数用于实现服务器的监听等待功能,它的函数原型如下:

所需头文件#include <sys/socket.h>
函数原型 int listen(int sockfd, int backlog);
函数传入值sockfd:套接字描述符
backlog:请求队列中允许的最大请求数,大多数系统默认值为5
函数返回值成功:0
出错:-1

需要注意的是listen 并未真正的接受连接,只是设置socket 的状态为监听模式,真正接受客户端连接的是accept 函数 。通常情况下,listen 函数会在 socket ,bind 函数之后调用,然后才会调用 accept 函数。

     listen函数只适用于SOCK_STREAM或SOCK_SEQPACKET 的socket 类型。如果socket 为 AF_INET ,则参数 backlog 最大值可设至128,即最多可以同时接受128个客户端的请求。

 

4)接受连接函数

      服务器处于监听状态时,如果模式可获得客户机的连接请求,此时并不是立即处理这个请求,而是将这个请求放在等待队列中,当系统空闲时,再处理客户机的连接请求,接受连接请求的函数时accept,函数原型如下:

所需头文件#include <sys/socket.h>
函数原型 int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
函数传入值

sockfd:套接字描述符

my_addr:用于保存客户端的地址,入参

addrlen:地址长度

函数返回值

成功:建立好连接的套接字描述符

出错:-1

 当 accept 函数接受一个连接时,会返回一个新的 socket 标识符,以后的数据传输与读取就是通过这个新的socket 编号来处理,原来参数中的 socket 也可以继续使用。接受连接以后,远程主机的地址和端口信息会保存在 addr 所指的结构体内。

下面是个实例,体验listen 、accept函数的使用:

[cpp] view plaincopy
在CODE上查看代码片派生到我的代码片
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <string.h>  
  4. #include <sys/types.h>  
  5. #include <sys/socket.h>  
  6. #include <unistd.h>  
  7. #include <netinet/in.h>  
  8. #include <arpa/inet.h>  
  9. #define PORT 2345  
  10.   
  11. int main()  
  12. {  
  13.     int sockfd,newsockfd;  
  14.     struct sockaddr_in addr,caddr;  
  15.     int addr_len = sizeof(struct sockaddr_in);  
  16.     int caddr_len = sizeof(struct sockaddr_in);  
  17.   
  18.     if((sockfd = socket(AF_INET,SOCK_STREAM,0)) < 0)  
  19.     {  
  20.         perror("socket error");  
  21.         exit(-1);  
  22.     }  
  23.     else  
  24.     {  
  25.         printf("socket successfully!\n");  
  26.         printf("socket id : %d\n",sockfd);  
  27.     }  
  28.   
  29.     memset(&addr,0,addr_len);  
  30.     addr.sin_family = AF_INET;  
  31.     addr.sin_port = htons(PORT);  
  32.     addr.sin_addr.s_addr = htonl(INADDR_ANY);  
  33.   
  34.     if(bind(sockfd,(struct sockaddr *)&addr,addr_len) == -1)  
  35.     {  
  36.         perror("bind error");  
  37.         exit(-1);  
  38.     }  
  39.     else  
  40.     {  
  41.         printf("bind successfully!\n");  
  42.         printf("local port : %d\n",PORT);  
  43.     }  
  44.   
  45.     if(listen(sockfd,5) == -1)  
  46.     {  
  47.         perror("listen error");  
  48.         exit(-1);  
  49.     }  
  50.     else  
  51.     {  
  52.         printf("listening...\n");  
  53.     }  
  54.   
  55.     if((newsockfd = accept(sockfd,(struct sockaddr *)&caddr,&caddr_len)) == -1)  
  56.     {  
  57.         perror("accept error");  
  58.         exit(-1);  
  59.     }  
  60.     else  
  61.     {  
  62.         printf("accepted a new connection ..\n");  
  63.         printf("new socket id : %d\n",newsockfd);  
  64.     }  
  65.   
  66.     return 0;  
  67. }  

执行程序,得到输出结果:

[cpp] view plaincopy
在CODE上查看代码片派生到我的代码片
  1. fs@ubuntu:~/qiang/netprogram/tmp$ ./lisacc   
  2. socket successfully!  
  3. socket id : 3  
  4. bind successfully!  
  5. local port : 2345  
  6. listening...  

程序运行到这停止,并一直在这里等待,说明本机计算机的 2345号端口正处于监听的状态,等待本机上的连接服务请求。此时打开浏览器,在浏览器地址栏中输入下列形式的地址:

[cpp] view plaincopy
在CODE上查看代码片派生到我的代码片
  1. http://192.168.3.51:2345/  

这个地址是笔者个人IP地址,按"ENTER" 键,这样浏览器会请求连接本地计算机上的2345号端口。此时终端中显示如下结果:

[cpp] view plaincopy
在CODE上查看代码片派生到我的代码片
  1. accepted a new connection ..  
  2. new socket id : 4  

表明程序已经接受了这个连接,并创建了一个新的套接口(ID为4),然后退出了程序。

 

5、请求连接函数

       所谓请求连接,是指在客户机向服务器发送信息之前,需要先发送一个连接请求,请求与服务器建立TCP通信连接。connect 函数可以完成这项功能,函数原型如下:

所需头文件#include <sys/socket.h>
函数原型 int connect(int sockfd, struct sockaddr * serv_addr, int addrlen);
函数传入值

sockfd:套接字描述符

sock_addr:服务器端地址

addrlen:地址长度

函数返回值

成功:0

出错:-1

这里ser_addr 是一个结构体指针,指向一个sockaddr 结构体,这个结构体存储着远处服务器的IP与端口号信息。


6、数据读写函数

TCP/UDP读写函数总结,注意函数要成对使用

1)send函数

     建立套接口并完成通信连接以后,可以把信息传送到远程主机上,这个过程就是信息的发送。而对于远程主机发送来的信息,本地主机需要进行接收处理。下面开始讲述这种面向连接的套接口信息发送与接收操作。

    用connect 函数连接到远程计算机以后,可以用 send 函数将应答信息发送给请求服务的本地主机,通信时双向的,并且通信的双方是对等的。

    send() 函数原型如下:

所需头文件#include <sys/socket.h>
函数原型 int send(int sockfd, const void*buf, int len, int flags);
函数传入值

sockfd:套接字描述符

buf:发送缓冲区的地址 入参

len:发送数据的长度

flags:一般为0

函数返回值

成功:实际发送的字节数

出错:-1

 

2)recv()函数

       函数recv 可以接收远程主机发送来的数据,并将这些数据保存到一个数组中,函数原型如下:

所需头文件#include <sys/socket.h>
函数原型 int recv(int sockfd, const void*buf, int len, int flags);
函数传入值

sockfd:套接字描述符

buf:存放接收数据的缓冲区 出参

len:接收数据的长度

flags:一般为0

函数返回值

成功:实际接收的字节数

出错:-1


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/402293.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux 代码格式化工具 indent

以下是我最喜欢的代码格式化脚本&#xff1a; #!/bin/shif [ $# -lt 1 ]; thenecho "Usage: $0 <file>"exit 1fi# format a source file(*.c, *.h)formatSrcfile(){indent -npro -nip -lp -npsl -npcs -i4 -ts4 -sob -l140 -ss -nsaf -nsai -nsaw -bl -bli 0 $…

Android处理ListView中的Item中的Button按钮不能点击的问题

问题描述&#xff1a;ListView列表中的Button按钮按钮不能点击 解决办法&#xff1a;在ListView中的Item项的布局文件中加上&#xff1a;android:descendantFocusability"blocksDescendants"&#xff0c;问题解决。

php curl拉取远程图片

<?php $url "图片绝对地址/thumbnail.jpg"; $filename curl.jpg; getImg($url, $filename); /**通过curl方式获取制定的图片到本地* 完整的图片地址* 要存储的文件名*/ function getImg($url "", $filename "") {if(is_dir(basename($fi…

Linux 下 NFS服务的搭建

NFS是Network File System的简写&#xff0c;即网络文件系统。 网络文件系统是许多操作系统都支持的文件系统中的一种&#xff0c;也被成为NFS。NFS允许一个系统在网络上与他人共享目录和文件。通过使用NFS&#xff0c;用户可以像访问本地文件一样访问远端系统上的文件。 NFS所…

GCC 参数详解

From: http://www.cppblog.com/SEMAN/archive/2005/11/30/1440.html 先附上三篇相关文章&#xff1a; LINUX下的C编译器GCC简介 linux上的C/C编译器gcc/egcs详解 gcc和g的区别(很详细的描述) [介绍] gcc and g分别是gnu的c & c编译器 gcc/g在执行编译工作的时候&#…

电子客票状态整理

1.OPEN FOR USE&#xff1a;客票有效 2.VOID&#xff1a;已作废 3.REFUND&#xff1a;已退票 4.CHECK IN&#xff1a;正在办理登机 5.USED/FLOWN&#xff1a;客票已使用 6.SUSPENDED&#xff1a;系统处理&#xff0c;或人为挂起禁止使用该票 7.PRINT/EXCH&#xff1a;电子客票已…

Linux 系统应用编程——线程基础

传送门&#xff1a;Linux多线程编程实例解析 . linux多线程编程——同步与互斥 . 传统多任务操作系统中一个可以独立调度的任务&#xff08;或称之为顺序执行流&#xff09;是一个进程。每个程序加载到内存后只可以唯一地对应创建一个顺序执行流&#xff0c;即传统意义的进程。…

利用indent格式化源文件的脚本

脚本一&#xff1a;格式化指定目录下的源文件(*.h, *.cpp...) #!/bin/sh# 格式化某目录下所有*.h, *.c, *.cpp, *.hh文件, 并将文件换行符转换成Linux下的格式if [ $# -lt 1 ]; thenecho "Usage: $0 <dir>"exit 1elsedir$1fi# format a source file(*.c, *.h,…

apple mach-o linker (id) error

在网上查了下&#xff0c;有网友说是因为有变量重名&#xff0c;仔细检查了下代码&#xff0c;UIGraphicsEndImageContext()写成uigraphicsendimagecontext()了&#xff0c;改过来就编译通过了。转载于:https://www.cnblogs.com/cc-Cheng/p/3341242.html

Struts入门(三)深入Struts用法讲解

访问Servlet APIAction搜索顺序动态方法调用指定多个配置文件默认ActionStruts 后缀接收参数处理结果类型1.访问Servlet API 首先我们了解什么是Servlet API httpRequest、httpResponse、servletContext  3个api对应jsp面向对象&#xff1a;request、response、application …

linux errno定义

以下内容来自于Ubuntu系统&#xff0c;请看执行情况&#xff1a; [zcmasm-generic #6]$pwd /usr/include/asm-generic [zcmasm-generic #7]$ls errno* -lh -rw-r--r-- 1 root root 1.6K Jun 19 2013 errno-base.h -rw-r--r-- 1 root root 5.2K Jun 19 2013 errno.h [zcmasm-g…

linux多线程编程——同步与互斥

一、 为什么要用多线程技术&#xff1f; 1、避免阻塞&#xff0c;大家知道&#xff0c;单个进程只有一个主线程&#xff0c;当主线程阻塞的时候&#xff0c;整个进程也就阻塞了&#xff0c;无法再去做其它的一些功能了。 2、避免CPU空转&#xff0c;应用程序经常会涉及到RPC&am…

黑马程序员_泛型

--------------------ASP.NetAndroidIOS开发、.Net培训、期待与您交流&#xff01; -------------------- 1. 泛型 1.概述 泛型是为了解决了集合中存储对象安全问题&#xff0c;如果集合中存数了不同类型的对象&#xff0c;那么读取出来后&#xff0c;操作取出的对象以为不…

菜鸟成长记(十一)----- 操蛋的2016与未知的2017

现在已经2017.1.16号了&#xff0c;早就说着要写篇总结&#xff0c;骂骂特么操蛋的自己&#xff0c;当然这两三年来在这里骂的真特么不在少数了&#xff0c;但是都是特么一拖再拖&#xff0c;刚刚明明是在看TPO阅读的&#xff0c;但是特么实在是无法集中精神的看&#xff0c;作…

VS.NET版本与VC版本对应关系

vc6 -> vc6vs2003 -> vc7vs2005 -> vc8vs2008 -> vc9vs2010 -> vc10vs2012 -> vc11vs2013 -> vc12仅供参考&#xff01;

sql2008 获取表结构说明

SELECT 表名 case when a.colorder1 then d.name else end, 表说明 case when a.colorder1 then isnull(f.value,) else end, 字段序号 a.colorder, 字段名 a.name, 标识 case when COLUMNPROPERTY( a.id,a.name,IsIdentity)1 th…

Linux ALSA声卡驱动之四:Control设备的创建

声明&#xff1a;本博内容均由http://blog.csdn.net/droidphone原创&#xff0c;转载请注明出处&#xff0c;谢谢&#xff01; Control接口 Control接口主要让用户空间的应用程序&#xff08;alsa-lib&#xff09;可以访问和控制音频codec芯片中的多路开关&#xff0c;滑动控件…

【linux】信号量的值定义

参见文件&#xff1a;/usr/include/bits/signum.h /* Signal number definitions. Linux version.Copyright (C) 1995-2013 Free Software Foundation, Inc.This file is part of the GNU C Library.The GNU C Library is free software; you can redistribute it and/ormodi…

汇编学习笔记-序章

最近突然对汇编语言开始感兴趣&#xff0c;于是说干就干了。 之前也自学过一点汇编&#xff0c;是跟着王爽老师的《汇编语言(第3版) 》这本书学习的&#xff0c;已经是有5 6前年的样子了。当时觉得这本书写的非常通俗易懂是一本非常好的启蒙书籍&#xff0c;但是最近在翻阅的时…

jQuery 入门教程(5): 显示/隐藏内容

2019独角兽企业重金招聘Python工程师标准>>> jQuery的hide()和show()可以用来显示和隐藏内容。比如下面的例子&#xff1a;jQuery的hide()和show() 可以用来显示和隐藏内容。比如下面的例子&#xff1a; [html] view plain copy print ? <!doctype html> …