Linux 网络编程(1)——socket

1. 数据结构

1.1

  • sockaddr是通用的socket地址,sockaddr_in也是经常使用的地址,两者可以进行类型转换
struct sockaddr{
	unsigned short 	sa_family; 		//address family, AF_xxx
  	char 			sa_data[14];  	//14 bytes of protocol address
}
  • sa_family是地址家族,一般都是"AF_xxx"的形式,通常大多用的是都是AF_INET,代表TCP/IP协议族
  • sa_data是14字节协议地址

1.2 sockaddr_in

struct sockaddr_in{
	short int   		sin_family;     // Address family     
    unsigned short int  sin_port; 		// Port number     
    struct in_addr   	sin_addr;      	// Internet address
    unsigned char   	sin_zero[8];    // Same size as struct sockaddr
}
  • sin_family指代协议族,在socket编程中只能是AF_INET
  • sin_port存储端口号(使用网络字节顺序)
  • sin_addr存储IP地址,使用in_addr这个数据结构
  • sin_zero是为了让sockaddr与sockaddr_in两个数据结构保持大小相同而保留的空字节
  • sockaddr_in和sockaddr是并列的结构,指向sockaddr_in的结构体的指针也可以指向sockaddr的结构体,并代替它
  • 也就是说,你可以使用sockaddr_in建立你所需要的信息,然后用进行类型转换就可以了

1.3 in_addr

struct   in_addr{    
	union{  
		struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b;  
        struct { u_short s_w1,s_w2; } S_un_w;  
        u_long S_addr;   
}

1.4 例子:

int   sockfd;  
struct   sockaddr_in   my_addr;  					//声明一个sockaddr_in结构体my_addr
sockfd   =   socket(AF_INET,   SOCK_STREAM,   0);   //初始化一个sockfd
   
my_addr.sin_family  =   AF_INET;     				//协议
my_addr.sin_port   	=   htons(MYPORT);     			//端口
my_addr.sin_addr.s_addr   =   inet_addr("192.168.0.1");  	//网络地址,inet_addr将字符串转为十六进制,比如(0xC0A80001)
   
bzero(&(my_addr.sin_zero),   8);     				//填充空字节    
bind(sockfd,   (struct   sockaddr   *)&my_addr,   sizeof(struct   sockaddr));	//绑定
	

2.系统函数

2.1 socket

  • socket()函数是任何套接口网络编程中第一个使用的函数,它向用户提供一个套接字,即套接口描述文件字,它是一个整数。如同文件描述符一样,是内核标识一个IO结构的索引。通过socket函数,我们指定一个套接口的协议相关的属性,为进行使用socket api做好准备
	int socket(int family, int type, int protocol)
  • 输入:
    • family: 指定一个协议簇,也往往被称为协议域。系统存在许多可以的协议簇,常见有AF_INET──指定为IPv4协议,AF_INET6──指定为IPv6
    • type: 这个参数指定一个套接口的类型,套接口可能的类型有:SOCK_STREAM、SOCK_DGRAM、SOCK_SEQPACKET、SOCK_RAW等等,它们分别表明字节流、数据报、有序分组、原始套接口protocol 指定相应的传输协议,也就是诸如TCP或UDP协议等等,系统针对每一个协议簇与类型提供了一个默认的协议,我们通过把protocol设置为0来使用这个默认的值
  • 返回:非负描述字──成功, -1──出错

2.2 bind

	int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
  • 输入:
    +sockfd: socket文件描述符,也是socket函数的返回值
    +addr 构造出的IP地址加端口号
    +addrlen sizeof(addr)长度
    因为struct sockaddr* 是一个通用指针类型,addr实际上可以接受多种协议的sockaddr结构体,并且长度很肯能不一样,所以需要输入结构长度的参数
  • 返回:
    0——成功,-1——失败,

2.3 setsockopt

  • setsockopt()用来设置参数s 所指定的socket 状态
int setsockopt( int socket, int level, int option_name,const void *optval, socklen_t optlen)
  • 输入:
    • socket: socket文件描述符,也是socket函数的返回值
    • level: level 代表欲设置的网络层, 一般设成SOL_SOCKET 以存取socket 层
    • option_name: 参数optname 代表欲设置的选项:
      • SO_DEBUG 打开或关闭排错模式
      • SO_REUSEADDR 允许在bind ()过程中本地地址可重复使用
      • SO_TYPE 返回socket 形态.
      • SO_ERROR 返回socket 已发生的错误原因
      • SO_DONTROUTE 送出的数据包不要利用路由设备来传输
      • SO_BROADCAST 使用广播方式传送
      • SO_SNDBUF 设置送出的暂存区大小
      • SO_RCVBUF 设置接收的暂存区大小
      • SO_KEEPALIVE 定期确定连线是否已终止.
      • SO_OOBINLINE 当接收到OOB 数据时会马上送至标准输入设备
      • SO_LINGER 确保数据安全且可靠的传送出去
      • optval: optval 代表欲设置的值
      • optlen: optval 的长度
  • 返回:
    0——成功,-1——失败

2.4 getsockopt

  • getsockopt()会将参数s 所指定的socket 状态返回
int getsockopt(int sock, int level, int optname, void *optval, socklen_t *optlen)
  • 输入:
    • sock: socket文件描述符,也是socket函数的返回值
    • level: level 代表欲设置的网络层, 一般设成SOL_SOCKET 以存取socket 层
    • optname: 代表欲取得何种选项状态
    • optval: 指向欲保存结果的内存地址
    • optlen: 为该空间的大小
  • 返回:
    • 0——成功,-1——失败

2.5 listen()

int listen(int sockfd, int backlog)
  • sockfd是被listen函数作用的套接字,sockfd之前由socket函数返回。在被socket函数返回的套接字fd之时,它是一个主动连接的套接字,也就是此时系统假设用户会对这个套接字调用connect函数,期待它主动与其它进程连接,然后在服务器编程中,用户希望这个套接字可以接受外来的连接请求,也就是被动等待用户来连接。由于系统默认时认为一个套接字是主动连接的,所以需要通过某种方式来告诉系统,用户进程通过系统调用listen来完成这件事。
  • backlog定义内核监听队列的最大长度。APUE中指出,backlog只是一个提示,具体的数值实际上由系统决定

2.6 accept

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
  • 输入:
    • sockfd 上述listen函数指定的监听socket
    • addr 请求连接方(即客户端)地址
    • addrlen 客户端地址长度
  • 返回:
    • 函数执行成功返回一个新的连接socket,失败返回-1

2.7 connect

int connect(int sockfd, const struct sockaddr *server_addr, socklen_t *addrlen)
  • 输入:
    • sockfd socket函数返回一个socket
    • server_addr 服务端地址
    • addrlen 服务端地址地址长度
  • 返回:
    • 函数执行成功返回0,失败返回-1

2.8

int close(int sockfd)
  • 输入:
    • sockfd 待关闭的socket
  • 返回:
posted @ 2020-07-07 14:24  scbox  阅读(141)  评论(0)    收藏  举报