Linux网络编程第7/8章笔记

Socket编程基础知识

socket server side
  • 声明sockaddr_in的服务器地址
  • 绑定套接字, 返回fd ss = socket(AF_INET, SOCK_STREAM, 0);
  • 将sockaddr_in地址置空bzero(&server_addr, sizeof(server_addr));
  • 声明地址结构

    1
    2
    3
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    server_addr.sin_port = htons(PORT);
  • bind来监听fd err = bind(ss, (struct sockaddr*)&server_addr, sizeof(server_addr));

  • listen err = listen(ss, BACKLOG);
  • 开一个loop, 一直accept, sc = accept(ss, (struct sockaddr*)&client_addr, &addrlen);
  • fork一个子进程,由子进程处理
  • 子进程中,开一个loop, read具体的buffer, 返回响应的文字
socket client side
  • 绑定套接字s = socket(AF_INET, SOCK_STREAM, 0);
  • 置空bzero(&server_addr, sizeof(server_addr));
  • 声明地址结构
1
2
3
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
server_addr.sin_port = htons(PORT);
  • 将要链接的地址绑定到addr中inet_pton(AF_INET, argv[1], &server_addr.sin_addr);
  • 连接 connect(s, (struct sockaddr*)&server_addr, sizeof(struct sockaddr));
  • 从标准输入中获取用户输入文字,传输到服务器,并且将响应传到标准输出
1
2
3
4
5
6
7
8
for(;;){
size = read(0, buffer, 1024);
if (size >0){//如果输入了文字
write(s, buffer, size);
size = read(s, buffer, 1024);
write(1, buffer, size);
}
}

服务器和客户端信息的获取

字节序的转换
  • 小端字节序 (Little Endian, LE): 内存起始的地址存放低字节, 高字节顺序存放
  • 大端字节序 (Big Endian, BE): 内存起始的地址存放高字节,低字节顺序存放

检查一个系统是大端字节序还是小端字节序,声明一个union类型,里面存放int和 byte[2],给int赋值,然后将byte拆开访问

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
typedef union {
unsigned short int value;// short为16位
unsigned char byte[2];
} to;

int main(int argc, char *argv[]){
to typeorder;
typeorder.value = 0xabcd;
if(typeorder.byte[0] == 0xcd && typeorder.byte[1] == 0xab){
printf("low endian byte order, byte[0]:0x%x, byte[1]:0x%x", typeorder.byte[0], typeorder.byte[1]);
}
if(typeorder.byte[0] == 0xab && typeorder.byte[1] == 0xcd){
printf("high endian byte order, byte[0]:0x%x, byte[1]:0x%x", typeorder.byte[0], typeorder.byte[1]);
}

return 0;
}
  • htonl 主机到网络字节序, 长整形
  • htons 主机到网络字节序, 短整形
  • ntohl 网络到主机字节序,长整形
  • ntohs 网络到主机字节序, 短整形

当转换32位的字节序的时候,需要将byte[2]变成byte[4]

字符串ip和二进制ip的转换
  • in_addr_t inet_aton(const char *cp, struct in_addr *inp) 将四点分段式IP转换成in_addr值
  • in_addr_t inet_addr(const char *cp)字符串转换成in_addr值
  • in_addr_t inet_network(const char *cp) 字符串地址的网络部分转成in_addr类型
  • char *inet_ntoa(struct in_addr_in) 将in_addr转成字符串
  • in_addr_t inet_lnaof(struct in_addr_in) 获得地址的主机部分
  • in_addr_t inet_netof(struct in_addr_in) 获得地址的网络部分
fd判断,是否是socket的fd

使用函数issockettype

获取主机信息

struct hostent *gethostbyname(const char *name)
返回的类型为hostnet

1
2
3
4
5
6
7
struct hostent {
char *h_name;//主机的正式名称
char **h_aliases;//别名列表
int h_addrtype;//主机地址类型
int h_length;//地址长度
char **h_addr_list;//地址列表
}