1、Linux支持6种类型的套接字接口,其中,最常用的是两种:数据流套接字和数据报套接字。
2、TCP/IP协议的套接字地址结构是sockaddr_in,在系统头文件<netinet/in.h>中定义。
结构sockaddr_in中的TCP或UDP端口号sin_port和IP地址sin_addr都是以网络字节顺序存储的。
3、面向连接的套接字函数
(1)socket函数创建一个套接字描述符。
#include <sys/types.h>
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
(2)connect函数用于与服务器建立一个连接。
int connect(int sockfd, struct sockaddr * servaddr, int addrlen);
(3)bind函数将本地地址与套接字绑定在一起。
int bind(int sockfd, struct sockaddr * myaddr, int addrlen);
(4)listen函数将一个套接字装换为倾听套接字(listening socket)
int listen(int sockfd, int backlog);
(5)accept函数从倾听套接字的完成连接队列中接收一个连接。如果完成连接队列为空,那么这个进程休眠。
int accept(int sockfd, struct sockaddr * addr, int *addrlen);
(6)close函数关闭一个套接字描述符。
int close(int sockfd);
(7)函数read和write从套接字读和写数据。
int read(int sockfd, char * buff, int len);
int write(int sockfd, char * buff, int len);
4、面向连接套接字应用程序流程图
5、例子
编写一个客户机-服务器程序,其中客户机使用流套接字向服务器请求日期和时间,服务器在收到请求后,回答请求并显示出客户的地址。
(1) StreamSocketClient.c:
/* * StreamSocketClient.c * * Created on: Aug 24, 2013 * Author: root */ #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #define MAXBUFFSIZE 256 #define PORT 6666 #define HOST_ADDR "127.0.0.1" int main(){ int sockfd, n; char recvbuff[MAXBUFFSIZE]; struct sockaddr_in servaddr; sockfd = socket(AF_INET, SOCK_STREAM, 0); if(sockfd < 0){ printf("Socket created failed.\n"); return -1; } servaddr.sin_family = AF_INET; servaddr.sin_port = htons(6666); servaddr.sin_addr.s_addr = htonl(INADDR_ANY); printf("connecting...\n"); if(connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0){ printf("Connect server failed.\n"); return -1; } while((n = read(sockfd, recvbuff, MAXBUFFSIZE)) > 0){ recvbuff[n] = 0; fputs(recvbuff, stdout); } if(n < 0){ printf("Read failed.\n"); return -2; } return 0; }
(2) StreamSocketServer.c:
/* * StreamSocketServer.c * * Created on: Aug 24, 2013 * Author: root */ #include <time.h> #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #define LISTENQ 5 #define MAXLINE 512 int main(){ int listenfd, connfd; socklen_t len; struct sockaddr_in servaddr, cliaddr; char buff[MAXLINE]; time_t ticks; listenfd=socket(AF_INET,SOCK_STREAM, 0); if(listenfd < 0){ printf("Socket created failed.\n"); return -1; } servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(6666); if(bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0){ printf("bind failed.\n"); return -1; } printf("listening ...\n"); listen(listenfd, LISTENQ); while(1){ len = sizeof(cliaddr); connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &len); printf("connect from %s, port %d\n", inet_ntoa(cliaddr.sin_addr.s_addr), ntohs(cliaddr.sin_port)); ticks = time(NULL); //获取当前时间 sprintf(buff, "% .24s\r\n", ctime(&ticks)); //ctime函数:转换时间为标准时间字符串,并返回。 write(connfd, buff, strlen(buff)); close(connfd); } }
具体流套接字通信结果: