Linux套接字编程

来源:互联网 发布:淘宝上好看的包包店铺 编辑:程序博客网 时间:2024/06/06 02:08

在网络里面,每一个节点(计算机或路由器)都有一个网络地址,也就是IP地址,两个进程通信时,首先要确定各自所在的网络节点的网络地址,网络地址只能确定进程所在的计算机,一个计算机可能同时运行多个进程,为了确定要通信的进程,仅仅有网络地址还是不够的,套接字还要其他信息,端口号。一台计算机里,一个端口号一次只能分配给一个进程,端口号和进程之间是一种一一对应关系。端口号只有本地意义,不同计算机上的相同的端口号是没有什么联系的。一些端口号是固定早就被分配了的。一个新的应用程序出现,必须给它指派一个“周知"的端口号,否则其他的应用程序进程就无法和它进行交互。还有一些一般的端口号是随时分配给请求通信的客户进程的。</span>

套接字有两个

struct sockaddr  {    __SOCKADDR_COMMON (sa_);/* Common data: address family and length.  */    char sa_data[14];/* Address data.  */  };

这是所说的通用套接字,由于历史原因,反正我也不知道什么原因,特定与某种协议的套接字结构指针都要强制转换为通用套接字指针,以实现协议无关性。

struct sockaddr_in  {    __SOCKADDR_COMMON (sin_);    in_port_t sin_port;/* Port number.  */    struct in_addr sin_addr;/* Internet address.  */    /* Pad to size of `struct sockaddr'.  */    unsigned char sin_zero[sizeof (struct sockaddr) -   __SOCKADDR_COMMON_SIZE -   sizeof (in_port_t) -   sizeof (struct in_addr)];  };

这个是IPv4的套接字,与通用套接字不同的是,sockaddr_in将ip地址和端口号分开为不同的成员,套接字的通信地址类型有很多,在socket.h里面,IPv4对应的是AF_INET,IPV6对应的是AF_INET6。一般用到的就是这两个。

socket函数为套接字在sockfs文件系统中分配一个新的文件和dentry对象,并通过文件描述符把他们与调用进程联系起来,进程可以像访问一个已经打开的文件一样访问套接字

在sockfs中的对应文件,但进程不能调用open来访问文件,因为sockfs文件系统没有可视安装点,其中的文件永远不会出现在系统目录树上,当套接字关闭时,内核会自动删

除scokfs的inodes。

/*本机即做服务器又做客户端测试TCP链接,运行程序后在浏览器输入http://localhost:9000/,shell窗口会显示新的ID*/#include <stdio.h>#include <stdlib.h>#include <netdb.h>#include <unistd.h>#include <errno.h>#include<arpa/inet.h>#include<sys/socket.h>#include<sys/types.h>#include<string.h>#define PATH_MAX 128 //主机名数组#define PORT 9000int main(){    int sockfd,newsockfd;/*定义两个套接字描述符*/    struct sockaddr_in addr;/*IPv4类型的套结字地址数据结构*/    int addr_len=sizeof(struct sockaddr_in);//记录结构大小,后面会作为参数*/    if((sockfd=socket(AF_INET,SOCK_STREAM,0))<0)//创建一个套结字*/    {        //地址协议族IPv4,套结字类型是流套结字*/        perror("socket");        exit(0);    }    else    {        printf("creat socket success!sockid :%d\n",sockfd);    }    bzero(&addr,sizeof(struct sockaddr_in));//先清空结构    addr.sin_family=AF_INET;//设置地址协议族    addr.sin_port= htons(PORT);//端口号    addr.sin_addr.s_addr=htonl(INADDR_ANY);//ip地址是本机地址    if(bind(sockfd,(struct sockaddr *)(&addr),sizeof(struct sockaddr))<0)    {        //把刚刚创建好的套结字和端口绑定        perror("bind");        exit(0);    }    else    {        printf("bind success!\n");    }    if(listen(sockfd,5)<0)//开始监听允许最大请求树是5    {        perror("listen");        exit(1);    }    else    {        printf("listening.....\n");    }    if((newsockfd=accept(sockfd,(struct sockaddr *)(&addr),&addr_len))<0)        //调用accept接受一个请求连接,成功后会返回一个新的套结字描述符号以后可以用这个新的通信    {        perror("accept");        exit(2);    }    else    {        printf("accept a new connection.new socket id: %d\n",newsockfd);    }    close(sockfd);    return 0;}





0 0