Linux下的TCP Socket通信
一、socket函数 1、头文件: #include <sys/types.h> /* See NOTES */ #include <sys/socket.h> 2、函数原型: int socket(int domain,int type,int protocol); socket函数类似于open,用来打开一个网络连接,如果成功则返回一个网络文件描述符(int类型),之后我们操作这个网络连接都通过这个网络文件描述符。 dimain:域,网络域,网络地址范围(IPV4或IPV6等),也就是协议簇 type:指定套接字类型:SOCK_STREAM(TCP网络)、SOCK_DGRAM(UDP)、SOCK_SEQPACKET protocol:指定协议,如果指定0,表示使用默认的协议 3、函数形参: 3.1、domain:(域) AF_INET ?ip AF_PACKET ? ? ? ??packet ? ? ? ??低级数据包接口 PF_PACKET 不懂,待了解 PF_INET ?待了解(AF开头的表示地址族,PF开头的表示协议族,协议族包含多个地址族,但是当前这种还从未实现,而在<sys/socket.h>中PF的值总是与AF的值相等的) 3.2、type:(套接字类型): SOCK_RAW ? 原始套接字 ? ——>使用原始套接字时候调用,原始套接字也就是链路层协议 SOCK_STREAM ?字节流套接字 ?——>提供顺序,可靠,双向,基于连接的字节流。 可以支持带外数据传输机制。例如:TCP协议、FTP协议 SOCK_DGRAM ? ? ? ? 数据报套接字 ?——>支持数据报(无连接,不可靠的固定最大长度的消息)例如:UDP协议 SOCK_SEQPACKET ? 有序分组套接字 ? ?——>为固定最大长度的数据报提供有序,可靠,双向连接的数据传输路径; 消费者需要利用每个输入系统调用读取整个分组 3.3、protocol(协议): IPPROTO_IP ? IP传输协议 IPPROTO_TCP ? TCP传输协议 IPPROTO_UDP ? ? UDP协议 IPPROTO_SCTP ? ?SCTP传输协议 IPPROTO_ICMP ? ? ? ? ?ICMP协议 IPPROTO_IGMP ? ?IGMP协议 一般情况下IPPROTO_TCP、IPPROTO_UDP、IPPROTO_ICMP协议用的最多,UDP协议protocol就取IPPROTO_UDP,TCP协议protocol就取IPPROTO_TCP;一般情况下,我们让protocol等于0就可以,系统会给它默认的协议。但是要是使用raw socket协议,protocol就不能简单设为0,要与type参数匹配. 4、返回值: 成功时返回一个小的非负整数值,他与文件描述符类似,我们称为套接字描述符,简称sockfd。失败,则返回-1。 5、例子: /*---------------------创建一个监听socket-------------------*/ ??? if ((listenfd = socket(AF_INET,SOCK_STREAM,0)) == -1) ??? { ??????? perror("socket() errorn"); ??????? exit(1); } 二、bind函数 1、头文件: #include <sys/types.h> /* See NOTES */ 2、函数原型: int bind(int sockfd,const struct sockaddr *addr,socklen_t addrlen); 服务端套接字绑定自己的IP地址与端口号,客户端那边可以不写,内核会给它分配一个临时的端口。 3、函数形参: 3.1、sockfd:服务器或者客户端自己创建的socket 3.2、addr:服务器或者客户端自己的地址信息(协议族、IP、端口号) 3.3、addrlen:服务器或者客户端自己的地址信息的长度 4、返回值: 绑定成功,返回0,失败返回-1 5、例子: ??? /*---------------------绑定IP和端口bind----------------------*/ ??? bzero(&server,sizeof(server)); ??? server.sin_family = AF_INET; ??? server.sin_port = htons(port); ??? server.sin_addr.s_addr = inet_addr(ip); ? ??? if (bind(listenfd,(struct sockaddr *)&server,sizeof(server)) == -1) ??? { ??????? perror("bind() errorn"); ??????? exit(1); ??? } 三、connect函数 1、头文件: #include <sys/types.h> /* See NOTES */ 2、函数原型: int connect(int sockfd,socklen_t addrlen); TCP客户端通过connect函数与服务端连接,进行通信。 3、函数形参: 3.1、sockfd(客户端自己创建的sock) 3.2、addr(服务端地址族、服务端IP地址、服务端端口号) 3.3、addrlen(服务端地址字节长度) 4、返回值: 连接成功,返回0,连接失败,返回-1 5、例子: struct sockaddr_in client; addrlen = sizeof(client); ??????? if ((connetfd = accept(listenfd,(struct sockaddr *)&client,&addrlen)) == -1) ??????? { ??????????? perror("accept() errorn"); ??????????? exit(1); ??????? } 接下来给出一个大例子,tcp——socket套接字通信,结合sqlite3数据库操作 #include <stdio.h> #include <stdlib.h> #include <netinet/in.h> #include <sys/socket.h> #include <sys/types.h> #include <unistd.h> #include <string.h> ? int main() { ??? struct sockaddr_in server; ??? struct sockaddr_in client; ??? int listenfd,connetfd; ??? char ip[20]; ??? int port; ??? int addrlen; ??? char rebuf[100]; ??? char wrbuf[100]; ??? char tmp[100]; ??? int revlen; ??? /*---------------------创建一个监听socket-------------------*/ ??? if ((listenfd = socket(AF_INET,0)) == -1) ??? { ??????? perror("socket() errorn"); ??????? exit(1); ??? } ? ??? /*----------------------输入要监听的IP和端口----------------------*/ ??? printf("Please input the ip:n"); ??? scanf("%s",ip); ??? printf("Please input the port:n"); ??? scanf("%d",&port); ? ??? /*---------------------绑定IP和端口bind----------------------*/ ??? bzero(&server,sizeof(server)); ??? server.sin_family = AF_INET; ??? server.sin_port = htons(port); ??? server.sin_addr.s_addr = inet_addr(ip); ? ??? if (bind(listenfd,(struct sockaddr *)&server,sizeof(server)) == -1) ??? { ??????? perror("bind() errorn"); ??????? exit(1); ??? } ??? /*----------------------开始监听listen-------------------*/ ??? if (listen(listenfd,20) == -1) ??? { ??????? perror("listen() errorn"); ??????? exit(1); ??? } ??? int client_pid = 0; ??? while (1) ??? { ??????? /*----------------------accept------------------*/ ??????? addrlen = sizeof(client); ??????? if ((connetfd = accept(listenfd,(struct sockaddr *)&client,&addrlen)) == -1) ??????? { ??????????? perror("accept() errorn"); ??????????? exit(1); ??????? } ??????? /*---------------------show client---------------*/ ??????? printf("connect successful!n"); ??????? printf("the client ip is %s,port is %dn",inet_ntoa(client.sin_addr),ntohs(port)); ??????? client_pid = fork(); ??????? if (client_pid == 0) ??????? { ??????????? //子进程 ??????????? close(listenfd); //关闭监听请求 ??????????? /*----------------------read and write----------*/ ??????????? int serial = 0; ??????????? while (1) ??????????? { ??????????????? bzero(rebuf,sizeof(rebuf)); ??????????????? revlen = read(connetfd,rebuf,sizeof(rebuf)); ??????????????? if ((memcmp("bye",3)) == 0) ??????????????? { ??????????????????? printf("Bye-bye then close the connect...n"); ??????????????????? break; ??????????????? } ??????????????? bzero(wrbuf,sizeof(wrbuf)); ??????????????? bzero(tmp,sizeof(tmp)); ??????????????? sprintf(tmp,"%d",serial); ??????????????? strcat(tmp,rebuf); ??????????????? bcopy(tmp,wrbuf,strlen(tmp)); ??????????????? write(connetfd,sizeof(wrbuf)); ??????????????? rebuf[revlen] = ‘ |