说在前面
- 环境: WSL
- 参考: UNIX网络编程
啥
- 简单来讲就是引用作为函数参数,该参数有初始值。在函数中,该参数值被更改,作为一个结果值“返回”。
void function(int *val_res) { if(*val_res > 0) *val_res = 0; else *val_res = -1; } int main() { int a = 1; function(&a); printf("The Result: %d", a); return 0; }
网络编程
-
通常,当往一个套接字函数(如connect函数)传递套接字地址结构(如sockaddr_in结构)时,该结构以引用形式来传递,即传递一个指向该结构的指针。该结构的长度也作为一个参数传递,结构长度的传递方式取决于该结构的传递方向:从进程到内核;从内核到进程。
-
进程→内核
- 函数bind、connect、sendto;这些函数一个参数是指向套接字地址结构的指针,一个是该结构的长度。举个栗子:
(补充:为何要强制类型转换?见上一节)struct sockadddr_in serv; /* ... */ connect(sockfd, (struct sockaddr *) &serv, sizeof(serv));
- 内核通过该指针以及指针指向的结构体大小将进程的数据复制到内核,然后进行进一步的处理。
- 在这些函数中,结构体长度只是作为参数传进去,并没有数据返回。
- 函数bind、connect、sendto;这些函数一个参数是指向套接字地址结构的指针,一个是该结构的长度。举个栗子:
-
内核→进程
- 函数accept、recvfrom、getsockname、getpeername;这些函数一个参数是指向套接字地址结构的指针,一个是指向表示结构体长度的变量的指针。举个栗子:
struct sockaddr_un cli; socklen_t len; //POSIX规范:socklen_t位uint32_t /* ... */ len = sizeof(cli); getpeername(unixfd, (struct sockaddr *)cli, &len);
- 在函数被调用时,结构长度是一个值,通过这个值内核在读/写结构时不会越界;在函数返回时,结构长度是一个函数返回的结果,通过这个值进程可以知道内核在该结构中写入的数据量大小。
- 在这些函数中,结构长度既是值又是结果。从内核返回时,若套接字地址结构的长度是固定的,那么返回值总是是对应的固定值(如IPv4的sockaddr_in为16);若套接字地址结构长度可变,那么返回值可能小于其最大值(见上一节)
- 函数accept、recvfrom、getsockname、getpeername;这些函数一个参数是指向套接字地址结构的指针,一个是指向表示结构体长度的变量的指针。举个栗子:
-
在网络编程中,最常见的值-结果参数是套接字结构地址长度,其他还有(暂未讨论):
- select函数
- getsockopt函数
- recvmsg函数,msghdr结构
- ifconf结构
- sysctl函数