学习总结:socket通信

目录

《Linux高性能服务器编程》  中对数据传输的解释

使用专用socket地址

服务器端

socket选项

客户端

参考文献


《Linux高性能服务器编程》  中对数据传输的解释

      在《Linux高性能服务器编程》的第五章中讲到:当格式化的数据在两台使用不同字节序的主机之间直接传递时,接收端必然错误的解释之。解决方法是:发送端总是将要发送的数据转换成大端字节序(网络字节序),接收端根据自身情况来决定是否将数据转换为小端字节序(主机字节序),或者不转换。

使用专用socket地址

首先选择地址族:AF_INET(IPV4),其次将IP地址和端口号都用网络字节序来表示。     

IPV4专用socket地址结构体:

struct sockaddr_in
{
    sa_family_t sin_family;  // 地址族
    u_int16_t sin_port;    // 端口号
    struct in_addr sin_addr;  // IPV4地址结构体
};


struct in_addr
{
    u_int32_t s_addr  //这里要放IPV4的地址,要用网络字节序来表示。
}

服务器端

首先设置文件描述符属性(setsockopt()函数);

其次就是初始化socket结构体(地址族选择AF_INET(IPV4协议族)将端口号和IP地址都用网络字节序表示);INADDR_ANY就是指定地址为0.0.0.0的地址,这个地址事实上表示不确定地址,或“所有地址”、“任意地址”。

最后将socket结构体所指的socket地址分配给为命名的文件描述符

服务器端代码如下:

    int  listenfd;
    struct sockaddr_in servaddr;
    listenfd = socket(AF_INET,SOCK_STREAM,0);
    if (listenfd == -1)
    {
        perror("socket error:");
        exit(1);
    }
    //一个端口释放后会等待两分钟之后才能再被使用,SO_REUSEADDR是让端口释放后立即就可以被再次使用。
    int reuse_addr = 1;
    setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &reuse_addr, sizeof(reuse_addr)) ;

    bzero(&servaddr,sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);//绑定所有网卡所有IP
    servaddr.sin_port = htons(8000);
    if (bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr)) == -1)
    {
        perror("bind error: ");
        exit(1);
    }

绑定完之后将该文件描述符设置为监听文件描述符,监听任务由内核来处理,但是此时还不监听,不是堵塞状态:

	ret = listen(listenfd, FDSIZE);

accept阻塞等待建立连接返回值是一个新的文件描述符,用来与之通信,之前的文件描述符还存在,并且继续监听客户端的连接请求:

    int clifd;
    struct sockaddr_in cliaddr;
    socklen_t  cliaddrlen = sizeof(cliaddr); 
    clifd = accept(listenfd,(struct sockaddr*)&cliaddr,&cliaddrlen);

socket选项

下面的两个系统调用是用来读取和设置socket文件描述符的属性的方法:

#include <sys/socket.h>
int getsockopt(int sock, int level, int optname, void *optval, socklen_t *optlen);
int setsockopt(int sock, int level, int optname, const void *optval, socklen_t optlen);

sock 是目标文件描述符;

level 是指定要操作哪个协议,一般选择SOL_SOCKET(通用的socket选项,和协议无关);

optname 指定选项的名字;上文选择的是SO_REUSEADDR(重用本地地址);

option_value 是指被操作选项的值;

option_len 是指被操作选项的长度;

客户端

要将IP地址和端口号都以网络字节序来表示

转换完之后,connect()阻塞等待服务器的应答

客户端代码如下:

	struct sockaddr_in servaddr;  
	int sockfd;

	sockfd = Socket(AF_INET, SOCK_STREAM, 0);
	bzero(&servaddr, sizeof(servaddr));   //  bzero函数  清零
	servaddr.sin_family = AF_INET;   
	inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr);  //将IP地址从字符串格式“127.0.0.1”转换成 网络地址格式 ,然后放在指定位置(&servaddr.sin_addr)	
	servaddr.sin_port = htons(8000); //htons将端口号从主机字节序转变成网络字节序
	connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));  // 在这里阻塞等待服务器端应答

参考文献

《Linux高性能服务器编程》 游双    章节 5.1

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值