Linux套接字编程

在网络里面,每一个节点(计算机或路由器)都有一个网络地址,也就是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 9000
int 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;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值