网络编程期末知识点总结

网络编程知识点总结

套接字地址,通用形式

1
2
3
4
5
struct sockaddr{  /*保存地址的结构*/
unsigned char sa_len; /*总长度*/
sa_family_t sa_family; /*地址族*/
char sa_data[14]; /*实际更长:地址值*/
}

互联网地址,互联网风格

1
2
3
4
5
6
7
struct sockaddr_in{
unit8_t sin_len; /*总长度*/
sa_family_t sa_family; /*地址类型*/
in_port_t sin_port; /*协议端口号*/
struct in_addr sin_addr;/*IP地址*/
sin_zero[8]; /*未使用(设置为0)*/
}

两种传输服务的套接字类型

UDP:不可靠的数据报
TCP:可靠的、面向字节流的

UDP

客户端服务端之间没有连接

  • 发送数据前不握手
  • 发送方式显式的将IP目的地址和端口 # 附加到每个数据包
  • 接受方从收到的数据包中提取发送方的IP地址和端口号

UDP传输的数据可能丢失或接受顺序错误

简单的UDP程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#define LINELEN 128
/* 1) initialize sockaddr_in structure */
memset(&serverin, 0, sizeof(serverin));
serverin.sin_family = AF_INET;
serverin.sin_addr.s_addr = inet_addr(SERVER_HOST_ADDR);
serverin.sin_port = htons(SERVER_PORT);
/* 2) Create a socket */
if ((clientSocket = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
err(1, “create socket");
/* 3) formulate a request */
char buf[LINELEN+1];
int nchars; /* char count read in buf */
fgets(buf, sizeof(buf), stdin);
buf[LINELEN] = '\0'; /* insure null-terminated */
nchars = strlen(buf);
/* 4) send the request */
(void) sendto(clientSocket, buf, nchars, 0,
(struct sockaddr *)&serverin, sizeof(serverin));
/* 5) receive the reply */
if (recv(clientSocket, buf, sizeof(buf), 0) < 0)
err(1, "recv socket");
}
/* 6) handle the response */
fputs(buf, stdout);
fflush(stdout);

创建UDP和TCP通信端点sockfd

socket详解

TCP

1
int sockfd;sockfd = socket(PF_INET,SOCK_STREAM,0);

UDP

1
int sockfd;sockfd = socket(PF_INET,SOCK_DGRAM,0);

FD_ZERO、FD_SET、FD_CLR、FD_ISSET

  1. FD_ZERO(fd_set * fdset);将指定的文件描述符集清空,在对文件描述符集合进行设置前,必须对其进行初始化,如果不清空,由于在系统分配内存空间后,通常并不作清空处理,所以结果是不可知的。
  2. FD_SET(fd_set * fdset);用于在文件描述符集合中增加一个新的文件描述符。
  3. FD_CLR(fd_set * fdset);用于在文件描述符集合中删除一个文件描述符。
  4. FD_ISSET(int fd,fd_set * fdset);用于测试指定的文件描述符是否在该集合中。

select

1
int select(int nfds, fd_set *readset, fd_set *writeset,fd_set* exceptset, struct timeval *timeout);

nfds

需要检查的文件描述字个数(即检查到fd_set的第几位),数值应该比三组fd_set中所含的最大fd值更大,一般设为三组fd_set中所含的最大 fd值加1(如在readset,writeset,exceptset中所含最大的fd为5,则nfds=6,因为fd是从0开始的)。设这个值是为提高效率,使函数不必检查fd_set的所有1024位。

readset

用来检查可读性的一组文件描述字。

writeset

用来检查可写性的一组文件描述字。

exceptset

用来检查是否有异常条件出现的文件描述字。(注:错误不包括在异常条件之内)

timeout

用于描述一段时间长度,如果在这个时间内,需要监视的描述符没有事件发生则函数返回,返回值为0。

ai_family

ai_family参数指定调用者期待返回的套接口地址结构的类型。它的值包括三种:AF_INET,AF_INET6和AF_UNSPEC。如果指定AF_INET,那么函数九不能返回任何IPV6相关的地址信息;如果仅指定了AF_INET6,则就不能返回任何IPV4地址信息。AF_UNSPEC则意味着函数返回的是适用于指定主机名和服务名且适合任何协议族的地址

ntohs:将一个无符号短整型数从网络字节顺序转换为主机字节顺序。

htonl:将主机数转换成无符号长整形的网络字节顺序。

htons:htons是将整型变量从主机字节顺序转变成网络字节顺序, 就是整数在地址空间存储方式变为高位字节存放在内存的低地址处。

ntohl:ntohl()指的是ntohl函数,是将一个无符号长整形数从网络字节顺序转换为主机字节顺序, ntohl()返回一个以主机字节顺序表达的数。

FTP使用TCP传输而不是UDP

如果没有错误产生,则accept()返回一个描述所接受包的SOCKET类型的值。否则的话,返回INVALID_SOCKET错误,应用程序可通过调用WSAGetLastError()来获得特定的错误代码。如果addr与addrlen中有一个为零NULL,将不返回所接受的套接口远程地址的任何信息。

调用fork的返回值

  1. 在父进程中,fork返回新创建子进程的进程ID;
  2. 在子进程中,fork返回0;
  3. 如果出现错误,fork返回一个负值;

listen只能由TCP服务器程序调用

recvfrom 中 buflen不能为0

ssize_t read(int fd, void * buf, size_t count);成功返回读取的字节数,出错返回-1并设置errno,如果在调read之前已到达文件末尾,则这次read返回0。参数count是请求读取的字节数,读上来的数据保存在缓冲区buf中,同时文件的当前读写位置向后移

size_t write (int fd,const void * buf,size_t count);write()会把指针buf所指的内存写入count个字节到参数fd所指的文件内。当然,文件读写位置也会随之移动。如果顺利write()会返回实际写入的字节数。当有错误发生时则返回-1,错误代码存入errno中。

servname 、nodename、hints

1
2
3
4
5
6

int getaddrinfo(const char *restrict nodename, /* host 或者IP地址 */
const char *restrict servname, /* 十进制端口号 或者常用服务名称如"ftp"、"http"等 */
const struct addrinfo *restrict hints, /* 获取信息要求设置 */
struct addrinfo **restrict res); /* 获取信息结果 */

pthread

1
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void*), void *arg); 
1
2
3
4
5
int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr);  
int pthread_mutex_destory(pthread_mutex_t *mutex );
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
1
pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy);