基本的Socket函数解释

本文详细介绍了TCP和UDP套接字的工作原理及常用函数,包括socket(), bind(), listen(), accept(), connect(), sendto(), recvfrom()等,并解释了它们在网络编程中的应用。
[size=large][b] 基本TCP套接字[/b][/size]
[b]更加详细的信息请参考《Unix网络编程 卷1:套接字联网API》,里面详细列举出返回某种状态码时对应何种情况和其他更加详细的介绍。[/b]
TCP套接字建立过程需要服务器端按照 socket() -> bind() -> listen() -> accept() 然后等待客户端的连接请求,客户端需要 socket() -> connect() 来连接服务器。 连接成功两者通过write() read() 来进行交互。最后两者通过close() 来结束本次连接
[table]
|int [b][u]socket[/u][/b](int family, int type, int protocol)| 返回:若成功则为非负描述符,若出错则为-1|family,AF_INET 是IPv4协议,AF_INET6是IPv6协议;type,SOCK_STREAM是字节流套接字(TCP/IP) SOCK_DGRAM是数据包套接字(UDP) SOCK_RAW是原始套接字;protocol,IPPROTO_TCP是TCP传输协议 IPPROTO_UDP是UDP传输协议。|
|int [b][u]connect[/u][/b](int sockfd, const struct sockaddr *servaddr, socklen_t addrlen)|返回:若成功则为0,若出错则为-1|sockfd是客户端socket函数返回的套接字描述符|
|int [b][u]bind[/u][/b](sockfd, const struct sockaddr *myaddr, socklen_t addrlen)|返回:若成功则为0,若出错则为-1|sockfd是服务器端socket函数返回的套接字描述符|
|int [b][u]listen[/u][/b](int sockfd, int backlog)|返回:若成功则为0,若出错则为-1||
|int [b][u]accept[/u][/b](int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen)|||
[/table]


[size=large][b] 基本UDP套接字[/b][/size]
UDP是不安全的非连接的网络层协议。UDP服务器通过 socket() -> bind() - > recvfrom() 一直等待客户端的数据请求。 UDP客户端通过socket() -> sendto() 然后和服务器端进行数据交换。
[table]
|ssize_t [b][u]recvfrom[/u][/b](int sockfd, void *buff, size_t nbytes, int flags, sturct sockaddr *from, socklen_t addrlen)|返回:若成功则为读或写的字节数,若出错则为-1|
|ssize_t [b][u]sendto[/u][/b](int sockfd, const void *buff, size_t nbytes, int flags, const struct sockaddr *to, socklen_t addrlen)|返回:若成功则为读或写的字节数,若出错则为-1|
[/table]


[size=large][b] 其他函数[/b][/size]


[table]
|int [b][u]getsockopt[/u][/b](int sockfd, intlevel, int optname, void *optval, socklen_t *optlen)|返回:0--成功,-1--出错|
|int [b][u]setsockopt[/u][/b](int sockfd, intlevel, int optname, void *optval, socklen_t *optlen)|返回:0--成功,-1--出错|
[/table]
在Windows Socket API中对应如下:
[u][b]读取socket属性:[/b][/u]
int getsockopt(SOCKET s, int level, int optname, char FAR * optval, int FAR * optlen)
s为欲读取属性的套接字。level为套接字选项的级别,大多数是特定协议和套接字专有的。如IP协议应为 IPPROTO_IP。
optname为读取选项的名称
optval为存放选项值的缓冲区指针。
optlen为缓冲区的长度
用法:
int ttl=0; //读取TTL值
int rc = getsockop( s, IPPROTO_IP, IP_TTL, (char *)&ttl, sizeof(ttl));
设置socket属性:
int setsockopt(SOCKET s,int level, int optname,const char FAR * optval, int optlen)
s为欲设置属性的套接字。
level为套接字选项的级别,用法同上。
optname为设置选项的名称
optval为存放选项值的缓冲区指针。
optlen为缓冲区的长度
用法:
int ttl=32; //设置TTL值
int rc = setsockopt( s, IPPROTO_IP, IP_TTL, (char *)&ttl, sizeof(ttl));


以下这段 摘自百度百科:[url]http://baike.baidu.com/view/569217.htm[/url]
setsockopt()函数用于任意类型、任意状态套接口的设置选项值。尽管在不同协议层上存在选项,但本函数仅定义了最高的“套接口”层次上的选项。选项影响套接口的操作,诸如加急数据是否在普通数据流中接收,广播数据是否可以从套接口发送等等。
  有两种套接口的选项:一种是布尔型选项,允许或禁止一种特性;另一种是整形或结构选项。允许一个布尔型选项,则将optval指向非零整形数;禁止一个选项optval指向一个等于零的整形数。对于布尔型选项,optlen应等于sizeof(int);对其他选项,optval指向包含所需选项的整形数或结构,而optlen则为整形数或结构的长度。SO_LINGER选项用于控制下述情况的行动:套接口上有排队的待发送数据,且closesocket()调用已执行。参见closesocket()函数中关于SO_LINGER选项对closesocket()语义的影响。

[table]
| TCP_NODELAY是唯一使用IPPROTO_TCP层的选项,其他所有选项都使用SOL_SOCKET层。|
|*******************************************************************************|
| SO_BROADCAST BOOL 允许套接口传送广播信息。|
|  SO_DEBUG BOOL 记录调试信息。|
|  SO_DONTLINER BOOL 不要因为数据未发送就阻塞关闭操作。设置本选项相当于将SO_LINGER的l_onoff元素置为零。|
|  SO_DONTROUTE BOOL 禁止选径;直接传送。|
|  SO_KEEPALIVE BOOL 发送“保持活动”包。|
|  SO_LINGER struct linger FAR* 如关闭时有未发送数据,则逗留。|
|  SO_OOBINLINE BOOL 在常规数据流中接收带外数据。|
|  SO_RCVBUF int 为接收确定缓冲区大小。|
|  SO_REUSEADDR BOOL 允许套接口和一个已在使用中的地址捆绑(参见bind())。|
|  SO_SNDBUF int 指定发送缓冲区大小。|
|  TCP_NODELAY BOOL 禁止发送合并的Nagle算法。|
|  setsockopt()不支持的BSD选项有:|
|  选项名 类型 意义|
|  SO_ACCEPTCONN BOOL 套接口在监听。|
|  SO_ERROR int 获取错误状态并清除。|
|  SO_RCVLOWAT int 接收低级水印。|
|  SO_RCVTIMEO int 接收超时。|
|  SO_SNDLOWAT int 发送低级水印。|
|  SO_SNDTIMEO int 发送超时。|
|  SO_TYPE int 套接口类型。|
|  IP_OPTIONS 在IP头中设置选项。|
[/table]

[table]
|u_long [b][u]htonl[/u][/b](u_long hostlong)|将u_long类型的主机字节顺序格式的IP地址转换为TCP/IP网络字节顺序格式|
|u_short [b][u]htons[/u][/b](u_short hostshort)|将u_short类型的主机字节顺序格式的IP地址转换为TCP/IP网络字节顺序格式|
|u_long [b][u]ntohl[/u][/b](u_long netlong)|将TCP/IP网络字节顺序格式转换为u_long类型的主机字节顺序格式的IP地址|
|u_short [b][u]ntohs[/u][/b](u_short netshort)|将TCP/IP网络字节顺序格式转换为u_short类型的主机字节顺序格式的IP地址|
|unsigned long [b][u]inet_addr[/u][/b]( const char FAR * cp );|将用点分割的IP地址转换位一个in_addr结构的地址,这个结构的定义见笔记(一),实际上就是一个unsigned long值。计算机内部处理IP地址可是不认识如192.1.8.84之类的数据。 举例:inet_addr("192.1.8.84")=1409810880; inet_addr("127.0.0.1")= 16777343|
|char FAR * [b][u]inet_ntoa[/u][/b]( struct in_addr in );|char * ipaddr=NULL;
char addr[20];
in_addr inaddr;
inaddr. s_addr=16777343;
ipaddr= inet_ntoa(inaddr);
strcpy(addr,ipaddr);|
|int [b][u]WSAGetLastError[/u][/b](void )|读取当前错误值:每次发生错误时,如果要对具体问题进行处理,那么就应该调用这个函数取得错误代码。|
|int [b][u]getsockname[/u][/b](SOCKET s, struct sockaddr FAR * name, int FAR * namelen );|获取套接字的本地地址结构:s为套接字,name为函数调用后获得的地址值,namelen为缓冲区的大小。|
|int [b][u]getpeername[/u][/b](SOCKET s, struct sockaddr FAR * name, int FAR * namelen )|获取与套接字相连的端地址结构:s为套接字,name为函数调用后获得的端地址值,namelen为缓冲区的大小。|
|int [b][u]gethostname[/u][/b]( char FAR * name, int namelen )|获取计算机名:name是存放计算机名的缓冲区,namelen是缓冲区的大小。用法:
char szName[255];
memset(szName,0,255);
if(gethostname(szName,255)==SOCKET_ERROR)
{
//错误处理
}
返回值为:szNmae="xiaojin"|
|struct hostent FAR * [b][u]gethostbyname[/u][/b]( const char FAR * name );|根据计算机名获取主机地址。name为计算机名。
用法:
hostent * host;
char* ip;
host= gethostbyname("xiaojin");
if(host->h_addr_list[0])
{
struct in_addr addr;
memmove(&addr, host->h_addr_list[0],4);
//获得标准IP地址
ip=inet_ ntoa (addr);
}

返回值为:hostent->h_name="xiaojin"
hostent->h_addrtype=2 //AF_INET
hostent->length=4
ip="127.0.0.1"|

[/table]


[table]
|int [b][u]closesocket[/u][/b](SOCKET s)|关闭socket|
|int [b][u]shutdown[/u][/b](SOCKET s, int how)|不允许进行某些操作(包括读、写、读写等)|
[/table]
<think>好的,我现在需要回答用户关于socket函数的详细解释和功能,以及使用方法的问题。首先,我得回顾一下系统级指令,确保格式正确,比如行内数学表达式用$...$,独立公式用$$...$$,但这个问题可能不涉及数学公式,所以可能暂时不需要。不过要留意,如果有提到端口号或其他数值,可能需要用行内格式。用户引用了五个站内资料,我需要参考这些引用内容。引用1到5都涉及socket函数的不同方面,比如socket()、socketpair()、accept()、close()、shutdown()等。用户要问的是socket函数的作用和使用方法,所以重点应放在引用1和引用3、4、5的相关内容。首先,socket函数的作用是什么?根据引用1,socket函数用于创建套接字,是网络通信的基础。参数包括地址族(af)、类型(type)和协议(protocol)。返回值是套接字的文件描述符,失败返回-1。需要详细解释这三个参数的含义,比如af可以是AF_INET,type可能是SOCK_STREAM或SOCK_DGRAM,protocol通常为0,让系统自动选择。然后,使用方法方面,用户可能需要一个示例代码,比如在C语言中如何调用socket函数。例如:#include <sys/socket.h> intsockfd =socket(AF_INET,SOCK_STREAM,0);if (sockfd ==-1) {//错误处理} 需要说明各个参数的选择及其影响。比如AF_INET对应IPv4,SOCK_STREAM是TCP,SOCK_DGRAM是UDP。同时,错误处理也是重要部分,比如检查返回值是否为-1。另外,引用3提到accept函数返回已连接的套接字描述符,而原套接字仍保持开放,用于继续监听。这可能涉及到socket函数创建的套接字在服务器端的典型使用流程:创建、绑定、监听、接受连接。因此,可能需要简要说明socket函数在整个流程中的位置和作用。 引用4和5提到了关闭socket的方法,如close()和shutdown(),虽然用户要问的是socket函数,但可能在扩展问题中涉及,需要准备好相关答案。 用户可能需要知道常见错误及解决方法,比如参数选择不当导致创建失败。例如,如果type和protocol不匹配,可能会失败。或者地址族不支持的情况。 此外,注意事项部分,比如套接字正确初始化后需要调用bind、listen等函数,否则无法正常使用。同时,不同协议对参数的要求,比如TCP需要SOCK_STREAM,而UDP需要SOCK_DGRAM。 在回答结构上,按照用户的要求,结构清晰,分点解释作用、参数、返回值、示例、注意事项等。同时生成相关问题,可能涉及socket函数参数的具体含义、错误处理、与其他函数的关系,如bind、listen、accept等。需要检查是否符合中文回答,LaTeX语法是否正确,但此问题可能不涉及数学公式,所以暂时没问题。代码块需要用正确的语法高亮,比如C语言示例。最后,生成的相关问题需要围绕socket函数展开,比如参数详解、错误处理、使用场景、不同协议的创建方式等。</think>### socket函数的作用及使用方法 #### 一、socket函数的作用 socket函数是网络编程的核心工具,用于创建**套接字(socket)**,作为通信端点实现进程间或跨网络的交互[^1]。套接字是操作系统提供的抽象接口,支持TCP、UDP等协议的数据传输,是构建客户端/服务器模型的基础。 #### 二、函数原型及参数详解 ```c #include <sys/socket.h> int socket(int domain, int type, int protocol); ``` 1. **参数解释** - **domain(地址族)**: 指定通信域,常见值包括: - `AF_INET`: IPv4协议(如`192.168.1.1:80`) - `AF_INET6`: IPv6协议 - `AF_UNIX`: 本地进程间通信(UNIX域套接字) - **type(套接字类型)**: - `SOCK_STREAM`: 面向连接的TCP套接字(可靠传输) - `SOCK_DGRAM`: 无连接的UDP套接字(高效但不可靠) - **protocol(协议)**: 通常设为`0`,系统根据前两个参数自动选择协议(如TCP或UDP)[^1]。 2. **返回值** - 成功:返回**套接字文件描述符**(非负整数) - 失败:返回`-1`,可通过`errno`获取错误原因(如权限不足、参数无效)[^1]。 #### 三、使用示例(TCP服务器端) ```c #include <stdio.h> #include <sys/socket.h> int main() { int sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd == -1) { perror("Socket creation failed"); return 1; } printf("Socket created, fd: %d\n", sockfd); // 后续需调用bind、listen、accept等函数完成服务端配置[^3] return 0; } ``` #### 四、关键注意事项 1. **协议一致性** - 若`domain=AF_INET`且`type=SOCK_STREAM`,系统默认选择TCP协议。 2. **资源释放** - 套接字使用后需调用`close()`关闭,防止文件描述符泄漏[^4]。 3. **错误处理** - 检查返回值是否为`-1`,并结合`errno`定位问题(如`EACCES`表示权限不足)。 #### 五、典型应用场景 1. **TCP通信** - 创建`SOCK_STREAM`套接字后,需通过`bind()`绑定端口、`listen()`监听连接,最终由`accept()`接收客户端请求[^3]。 2. **UDP通信** - 使用`SOCK_DGRAM`套接字直接调用`sendto()`和`recvfrom()`收发数据。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值