C++套接字编程基础知识介绍

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/chengqiuming/article/details/89298442

一 点睛

Linux网络编程包括:用户态网络编程和内核态网络编程。

无论在Windows平台还是Linux平台,都对套接字实现了自己的一套编程接口。Windows下的Socket实现叫Windows Socket。Linux下的实现有两套:一套是伯克利套接口,起源于Berkeley Unix,这套接口很简单,得到了广泛应用,已经成为Linux网络编程事实上的标准;另一套是传输层接口,它是System V系统上网络编程API,所以这套编程接口更多是在Unix上使用。

Socket是在应用层和传输层之间的一个抽象层,它把TCP/IP层复杂的操作抽象为几个简单的接口供应用层调用,以实现进程在网络中通信。

Socket编程接口其实就是用户进程(应用层)和传输层或网络层之间的编程接口。

二 网络程序架构

一种是B/S架构:浏览器查看网站上网页就是这种架构下的应用。

一种是C/S架构:例如,我们计算机上安装的QQ程序就是客户端,而在腾讯公司内部还有服务器端程序。

基于套接字的网络编程,通常使用C/S架构。一个简单的客户机和服务器之间的通信过程如下:

1 客户机向服务器提出一个请求。

2 服务器收到客户机的请求,进行分析处理。

3 服务器将处理的结果返回客户机。

三 套接字类型

Linux下有3种类型套接字

  • 流套接字:SOCK_STREAM
  • 数据报套接字:SOCK_DGRAM
  • 原始套接字:SOCK_RAW

原始套接字与标准套接字(标准套接字包括流套接字和数据报套接字)的区别:原始套接字可以读写内核没有处理的IP数据包,而流套接字只能读取TCP协议的数据,数据报套接字只能读取UDP协议的数据。

四 套接字地址结构

1 点睛

AF 表示ADDRESS FAMILY 地址族,PF 表示PROTOCOL FAMILY 协议族,但这两个宏定义是一样的,所以使用哪个都没有关系。

Winsock2.h中#define AF_INET 2,#define PF_INET AF_INET,所以在windows中AF_INET与PF_INET完全一样。

而在Unix/Linux系统中,在不同的版本中这两者有微小差别。

对于BSD,是AF。

对于POSIX是PF。

UNIX系统支持AF_INET,AF_UNIX,AF_NS等

而DOS,Windows中仅支持AF_INET,它是网际网区域。

不同协议族的套接字地址的含义是不同的,如AF_INET的地址为struct sockaddr_in,

而域套接字AF_INET的地址为struct sockaddr_un

2 sockaddr_in说明

sockaddr_in定义位置:/usr/include/netinet/in.h

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)];
  };

__SOCKADDR_COMMON是一个宏,定义在/usr/include/bits/sockaddr.h

#define __SOCKADDR_COMMON(sa_prefix) \                  
  sa_family_t sa_prefix##family

\:续行符

##:连接前后两个参数

__SOCKADDR_COMMON (sin_);

宏展开后变为:

sa_family_t sin_family

sa_family_t定义于/usr/include/bits/sockaddr.h

typedef unsigned short int sa_family_t;

所以__SOCKADDR_COMMON (sin_);宏展开后的最终结果是:unsigned short int sin_family

五 主机字节序

1 点睛

小端字节序:数据的低字节存于内存低地址中,数据的高字节存于内存高字节中。

大端字节序:数据的低字节存于内存高地址中,数据的高字节存于内存低字节中。

2 测试主机的字节序

2.1 代码

#include <iostream>
using namespace std;

int main(int argc, char *argv[])
{
    int nNum = 0x12345678;
    char *p = (char*)&nNum;  //p指向存储nNum的内存的低地址
     
    if (*p == 0x12) cout << "This machine is big endian." << endl; //判断低地址是否存放的是数据高位
    else cout << "This machine is small endian." << endl;   
  
    return 0;
}

2.2 运行

[root@localhost test]# g++ -o test test.cpp
[root@localhost test]# ./test
This machine is small endian.

2.3 说明

这个机子是x86机子,x86机子基本都是小端模式。

六 网络字节序

1 点睛

网络字节序是TCP/IP中规定好的一种数据表示格式,它与具体的CPU类型,操作系统无关,从而可以保证数据在不同主机之间传输时能够被正确解释。网络字节顺序采用大端排序方式。

我们开发应用程序时,应该保证使用网络字节序,为此需要将数据由主机的字节序转换为网络字节序后再发出数据,接收方收到数据也要先转为主机字节序后再进行处理。

2 主机字节序和网络字节序相互转换的函数。

uint32_t htonl(uint32_t hostlong);   //32位主机转网络
uint16_t htons(uint16_t hostshort);  //16位主机转网络
uint32_t ntohl(uint32_t netlong);    //32位网络转主机
uint16_t ntohs(uint16_t netshort);   //16位网络转主机

 

没有更多推荐了,返回首页