深入浅出Linux工具与编程(socket 函数)

1.   基本套接字函数

(1)socket函数原型


socket(建立一个socket文件描述符)


所需头文件


#include <sys/types.h>

#include <sys/socket.h>


函数说明


建立一个socket文件描述符


函数原型


int socket(int domain, int type, int protocol)


函数传入值


domain


AF_INET:IPv4协议


AF_INET6:IPv6协议


AF_LOCAL:Unix域协议


AF_ROUTE:路由套接口


AF_KEY:密钥套接口


type


SOCKET_STREAM:双向可靠数据流,对应TCP


SOCKET_DGRAM:双向不可靠数据报,对应UDP


SOCKET_RAW:提供传输层以下的协议,可以访问内部网络接口,例如接收和发送ICMP报文


protocol


type为SOCKET_RAW时需要设置此值说明协议类型,其他类型设置为0即可


函数返回值


成功:socket文件描述符


失败:-1,失败原因存于error中

表18-1列出了当进行socket调用时,中协议簇(domain)与类型(type)可能产生的组合。

表18-1 socket中协议簇(domain)与类型(type)组合表


AF_INET


AF_INET6


AF_LOCAL


AF_ROUTE


AF_KEY


SOCK_STREAM


TCP


TCP


Yes


SOCK_DGRAM


UDP


UDP


Yes


SOCK_RAW


IPv4


IPv6


Yes


Yes

(2)bind函数原型


bind(将一个本地协议地址与socket文件描述符联系起来)


所需头文件


#include <sys/types.h>

#include <sys/socket.h>


函数说明


将一个协议地址与socket文件描述符联系起来


函数原型


int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)


函数传入值


sockfd


socket文件描述符


addr


my_addr指向sockaddr结构,该结构中包含IP地址和端口等信息


addrlen


sockaddr结构的大小,可设置为sizeof(struct sockaddr)


函数返回值


成功:0


失败:-1,失败原因存于error中

利用bind函数绑定地址时,可以指定IP地址和端口号,也可以指定其中之一,甚至一个也不指定。可以使用通配地址INADDR_ANY(为宏定义,其值等于0),它通知内核选择IP地址。表18-2列出了设置socket地址结构的几种方式,但在实际中,绑定的端口号都需要指定。

表18-2 设置socket地址结构的几种方式


进程指定


说 明


IP地址


端口


通配地址INADDR_ANY


0


内核自动选择IP地址和端口号


通配地址INADDR_ANY


非0


内核自动选择IP地址,进程指定端口号


本地IP地址


0


进程指定IP地址,内核自动选择端口号


本地IP地址


非0


进程指定IP地址和端口号

(3)listen函数原型


listen (等待连接)


所需头文件


#include <sys/types.h>

#include <sys/socket.h>


函数说明


等待连接


函数原型


int listen(int sockfd, int backlog)


函数传入值


sockfd


监听socket文件描述符


backlog


套接字排队的最大连接个数


函数返回值


成功:0


失败:-1,失败原因存于error中


特别说明


对于监听socket文件描述符sockfd,内核要维护两个队列,分别为未完成连接队列和已完成连接队列,这两个队列之和不超过backlog

 

(4)connect函数原型


connect(建立socket连接)


所需头文件


#include <sys/types.h>

#include <sys/socket.h>


函数说明


建立socket连接


函数原型


int connect(int sockfd, const struct sockaddr *serv_addr,

socklen_t addrlen)


函数传入值


sockfd


socket文件描述符


serv_addr


连接的网络地址和端口


addrlen


sockaddr结构的大小,可设置为sizeof(struct sockaddr)


函数返回值


成功:0


失败:-1,失败原因存于error中


附加说明


函数connect激发TCP的三路握手过程,出错返回有以下几种情况:

①     如果客户没有收到SYN分节的响应(总共75秒,这之间可能重发了若干次SYN),则返回ETIMEDOUT

②     如果对客户的SYN的响应是RST,则表明该服务器主机在指定的端口上没有进程在等待与之相连,函数返回错误ECONNREFUSED

③     如果客户发出的SYN在中间路由器上引发一个目的地不可达的ICMP错误,内核返回EHOSTUNREACH或ENETUNREACH错误(即ICMP错误)给进程

 

(5)accept函数原型


accept(接受socket连接)


所需头文件


#include <sys/types.h>

#include <sys/socket.h>


函数说明


接受socket连接,返回一个新的socket文件描述符,原socket文件描述符仍为listen函数所用,而新的socket文件描述符用来处理连接的读写操作


函数原型


int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)


函数传入参数


sockfd: socket文件描述符


addrlen:addr的大小,可设置为sizeof(struct sockaddr)


函数传出参数


addr:填入远程主机的地址数据


函数返回值


成功:实际读取字节数


失败:-1,错误代码存放在error中


附加说明


①     accept函数由TCP服务器调用,为阻塞函数,从已完成连接的队列中返回一个连接;如果该对列为空,则进程进入阻塞等待

②     函数返回的套接字为已连接套接字,而监听套接字仍为listen函数所用

(6)close函数原型


close (关闭连接的socket文件描述符)


所需头文件


#include <unistd.h>


函数说明


关闭连接的socket文件描述符


函数原型


int close(int sockfd)


函数传入值


sockfd:socket文件描述符


函数返回值


成功:0


失败:-1,失败原因存于error中


附加说明


①     close函数默认功能是将套接字置为“已关闭”标记,并立即返回给进程,这个套接字不能再为该进程所用

②     正常情况下,close将引发四个分节终止序列,但在终止前将发送已排队的数据

③     如果套接字描述符访问计数在调用close后大于0(多个进程共享同一个套接字的情况下),则不会引发TCP终止序列(即不会发送FIN分节)

 

(7)shutdown函数原型


shutdown(终止socket通信)


所需头文件


#include <sys/socket.h>


函数说明


终止socket通信


函数原型


int shutdown(int s, int how)


函数传入值


s


socket文件描述符


how


0(SHUT_RD):关闭socket连接的读这一半,不再接收套接字中的数据且现留在收缓冲区的数据作废


1(SHUT_WR):关闭socket连接的写这一半(半关闭),但留在套接字发送缓冲区中的数据都会被发送,后跟TCP连接终止序列,不管访问计数是否大于0,此后将不能再执行对套接字的任何写操作


2(SHUT_RDWR):socket连接的读、写都关闭


函数返回值


成功:0


失败:-1,失败原因存于error中

(8)read函数原型


read(从打开的socket文件流中读取数据)


所需头文件


#include <unistd.h>


函数说明


从打开的socket文件流中读取数据,这里仅说明此函数应用于socket的情况


函数原型


ssize_t read(int fd, void *buf ,size_t count)


函数传入参数


fd: socket文件描述符


count:最大读取字节数


函数传出参数


buf:读取数据的首地址


函数返回值


成功:实际读取字节数


失败:-1,错误代码存放在error中


附加说明


调用函数read从socket文件流中读取数据时,有如下几种情况:

①     套接字接收缓冲区接收数据,返回接收到的字节数

②     TCP协议收到FIN数据,返回0

③     TCP协议收到RST数据,返回-1,同时errno设置为ECONNRESET

④     进程阻塞过程中接收到信号,返回-1,同时errno设置为EINTR

 

(9)write函数原型


write(向socket文件流中写入数据)


所需头文件


#include <unistd.h>


函数说明


向socket文件流中写入数据,这里仅说明此函数应用于socket的情况


函数原型


ssize_t write (int fd,const void *buf,size_t count)


函数传入参数


fd: socket文件描述符


buf:写入数据的首地址


count:最大写入字节数


函数返回值


成功:实际写入的字节数


失败:-1,错误代码存放在error中


附加说明


调用函数write向socket文件流写数据时,有如下几种情况:

①        套接字发送缓冲区有足够空间,返回发送的字节数

②        TCP协议接收到RST数据,返回-1,同时errno设置为ECONNRESET

③        进程阻塞过程中接收到信号,返回-1,同时errno设置为EINTR

2.   高级套接字函数

recv和send函数提供了和read和write差不多的功能。不过它们提供了第四个参数来控制读写操作。

(1) send函数原型


send(通过socket文件描述符发送数据到对方)


所需头文件


#include <sys/types.h>

#include <sys/socket.h>


函数说明


通过socket文件描述符发送数据到对方


函数原型


ssize_t send(int s, const void *buf, size_t len, int flags)


函数传入值


s


socket文件描述符


buf


发送数据的首地址


len


发送数据的长度


flags


0:此时功能同write,flags还可以设为以下标志的组合


MSG_OOB:发送带外数据


MSG_DONTROUTE:告诉IP协议,目的主机在本地网络,没有必要查找路由表


MSG_DONTWAIT:设置为非阻塞操作


MSG_NOSIGNAL:表示发送动作不愿被SIGPIPE信号中断


函数返回值


成功:实际发送的字节数


失败:-1,失败原因存于error中

(2) recv函数原型


recv(通过socket文件描述符从对方接收数据)


所需头文件


#include <sys/types.h>

#include <sys/socket.h>


函数说明


通过socket文件描述符从对方接收数据


函数原型


ssize_t recv(int s, void *buf, size_t len, int flags)


函数传入值


s


socket文件描述符


len


可接收数据的最大长度


flags


0:此时功能同read,flags还可以设为以下标志的组合


MSG_OOB:接收带外数据


MSG_PEEK:查看数据标志,返回的数据并不在系统中删除,如果再次调用recv函数会返回相同的数据内容


MSG_DONTWAIT:设置为非阻塞操作


MSG_WAITALL:强迫接收到len大小的数据后才返回,除非有错误或有信号产生


函数传出值


buf


接收数据的首地址


函数返回值


成功:实际发送的字节数


失败:-1,失败原因存于error中

3.   套接字属性控制函数

系统提供getsockopt、setsockopt两函数获取和修改套接字结构中一些属性,通过修改这些属性,可以调整套接字的性能,进而调整应用程序的性能。

(1) getsockopt函数原型


getsockopt(获取套接字的属性)


所需头文件


#include <sys/types.h>

#include <sys/socket.h>


函数说明


获取套接字的属性


函数原型


int getsockopt(int s, int level, int optname,

void *optval, socklen_t *optlen)


函数传入值


s


socket文件描述符


level


SOL_SOCKET:通用套接字选项


IPPROTO_IP:IP选项


IPPROTO_TCP:TCP选项


optname


访问的选项名,具体见表18-3


optlen


optval的长度


函数传出值


optval


取得的属性值


函数返回值


成功:0


失败:-1,失败原因存于error中

表18-3 套接字属性表


level(级别)


optname(选项名


说明


数据类型


SOL_SOCKET


SO_BROADCAST


允许发送广播数据


int


SO_DEBUG


允许调试


int


SO_DONTROUTE


不查找路由


int


SO_ERROR


获得套接字错误


int


SO_KEEPALIVE


保持连接


int


SO_LINGER


延迟关闭连接


struct linger


SO_OOBINLINE


带外数据放入正常数据流


int


SO_RCVBUF


接收缓冲区大小


int


SO_SNDBUF


发送缓冲区大小


int


SO_RCVLOWAT


接收缓冲区下限


int


SO_SNDLOWAT


发送缓冲区下限


int


SO_RCVTIMEO


接收超时


struct timeval


SO_SNDTIMEO


发送超时


struct timeval


SO_REUSERADDR


允许重用本地地址和端口


int


SO_TYPE


获得套接字类型


int


SO_BSDCOMPAT


与BSD系统兼容


int


IPPROTO_IP


IP_HDRINCL


在数据包中包含IP首部


int


IP_OPTINOS


IP首部选项


int


IP_TOS


服务类型


int


IP_TTL


生存时间


int


IPPRO_TCP


TCP_MAXSEG


TCP最大数据段的大小


int


CP_NODELAY


不使用Nagle算法


int

(2)setsockopt函数原型


setsockopt(设置套接字的属性)


所需头文件


#include <sys/types.h>

#include <sys/socket.h>


函数说明


设置套接字的属性


函数原型


int setsockopt(int s, int level, int optname,

const void *optval, socklen_t optlen)


函数传入值


s


socket文件描述符


level


SOL_SOCKET:通用套接字选项


IPPROTO_IP:IP选项


IPPROTO_TCP:TCP选项


optname


设置的选项名,具体见表18-3


optval


设置的属性值


optlen


optval的长度


函数返回值


成功:0


失败:-1,失败原因存于error中

(3)getsockopt、setsockopt函数举例

sockopt.c源代码如下:

#include <stdio.h>

#include <sys/types.h>

#include <sys/socket.h>

int main()

{

int sockfd,optval,optlen = sizeof(int);

int sndbuf = 0 ;

int rcvbuf = 0 ;

int flag;

if((sockfd = socket(AF_INET,SOCK_STREAM,0))<0)

{

perror("socket") ;

return -1 ;

}

getsockopt(sockfd,SOL_SOCKET,SO_TYPE,&optval,&optlen);

printf("optval = %d\n",optval);

optlen = sizeof(sndbuf);

flag = getsockopt(sockfd,SOL_SOCKET,SO_SNDBUF,&sndbuf,&optlen);

printf("sndbuf=%d\n",sndbuf) ;

printf("flag=%d\n",flag) ;

sndbuf = 51200;

flag = setsockopt(sockfd,SOL_SOCKET,SO_SNDBUF,&sndbuf, optlen);

sndbuf=0 ;

flag = getsockopt(sockfd,SOL_SOCKET,SO_SNDBUF,&sndbuf,&optlen);

printf("sndbuf=%d\n",sndbuf) ;

printf("flag=%d\n",flag) ;

close(sockfd);

return 0 ;

}

编译 gcc sockopt.c -o sockopt。

执行 ./sockopt, 执行结果如下:

optval = 1

sndbuf=16384

flag=0

sndbuf=102400

flag=0

4.   UDP读写函数

UDP套接字是无连接协议,必须使用sendto函数发送数据,必须使用recvfrom函数接收数据,发送时需指明目的地址。sendto函数与send功能基本相同,recvfrom与recv功能基本相同,只不过sendto函数和recvfrom函数参数中都带有对方地址信息,这两个函数是专门为UDP协议提供的。

(1)sendto函数原型


sendto(通过socket文件描述符发送数据到对方)


所需头文件


#include <sys/types.h>

#include <sys/socket.h>


函数说明


通过socket文件描述符发送数据到对方,用于UDP协议


函数原型


ssize_t sendto(int s, const void *buf, size_t len, int flags,

const struct sockaddr *to, socklen_t tolen)


函数传入值


s


socket文件描述符


buf


发送数据的首地址


len


发送数据的长度


flags


0:默认方式发送数据,flags还可以设为以下标志的组合


MSG_OOB:发送带外数据


MSG_DONTROUTE:告诉IP协议,目的主机在本地网络,没有必要查找路由表


MSG_DONTWAIT:设置为非阻塞操作


MSG_NOSIGNAL:表示发送动作不愿被SIGPIPE信号中断


to


存放目的主机IP地址和端口信息


tolen


to的长度,可设置为sizeof(struct sockaddr)


函数返回值


成功:实际发送的字节数


失败:-1,失败原因存于error中

(2) recvfrom函数


recv(通过socket文件描述符从对方接收数据)


所需头文件


#include <sys/types.h>

#include <sys/socket.h>


函数说明


通过socket文件描述符从对方接收数据,用于UDP协议


函数原型


ssize_t recvfrom(int s, void *buf, size_t len, int flags,

struct sockaddr *from, socklen_t *fromlen)


函数传入值


s


socket文件描述符


len


可接收数据的最大长度


flags


0:默认方式接收数据,flags还可以设为以下标志的组合


MSG_OOB:接收带外数据


MSG_PEEK:查看数据标志,返回的数据并不在系统中删除,如果再次调用recv函数会返回相同的数据内容


MSG_DONTWAIT:设置为非阻塞操作


MSG_WAITALL:强迫接收到len大小的数据后才返回,除非有错误或有信号产生


fromlen


from的长度,可设置为sizeof(struct sockaddr)


函数传出值


buf


接收数据的首地址


from


存放发送方的IP地址和端口


函数返回值


成功:实际发送的字节数


失败:-1,失败原因存于error中

 摘录自《深入浅出Linux工具与编程》

时间: 2024-08-01 01:56:49

深入浅出Linux工具与编程(socket 函数)的相关文章

Linux下c编程rename函数导致的问题

前段时间在部署代码的时候,发现一个比较"诡异"的问题 相同的环境下(CentOs 6.5),开发说在其本机的虚拟机汇总测试是正常的,部署到正式环境中时,就会出现问题.相同的函数,总是执行失败.在另一台测试也是完全正常 开发说是服务器安装的原因,来来回回安装了N次.真TM郁闷 然后又说是权限的问题,包的问题,自己安装,服务器拿回家升级,重买服务器.这个拿回去给他妈用等等等等--我都懒的理他 首先说权限问题,我说跟测试正常的那台机器完全相同,说不行,好吧,给你777 又说是包没安装,我说那

linux c网络编程之函数

1. struct protoent *protocol=getprotobyname(char *p); 功能:通过协议名获取协议类型信息 解释:p为字符串指针,指向一个协议名,如icmp,struct protoent及函数在<netdb.h>中定义,protocol->p_proto为协议类型值. 2.

linux socket网络编程 常用函数及头文件

转自:http://blog.chinaunix.net/u3/102500/showart_2065640.html 一 三种类型的套接字: 1.流式套接字(SOCKET_STREAM) 提供面向连接的可靠的数据传输服务.数据被看作是字节流,无长度限制.例如FTP协议就采用这种. 2.数据报式套接字(SOCKET_DGRAM) 提供无连接的数据传输服务,不保证可靠性. 3.原始式套接字(SOCKET_RAW) 该接口允许对较低层次协议,如IP,ICMP直接访问. 二 基本套接字系统调有有如下一

Linux 高性能服务器编程——高级I/O函数

重定向dup和dup2函数 [cpp] view plaincopyprint? #include <unistd.h> int dup(int file_descriptor); int dup2(int file_descriptor_one, int file_descriptor_two); dup创建一个新的文件描述符, 此描述符和原有的file_descriptor指向相同的文件.管道或者网络连接. dup返回的文件描述符总是取系统当前可用的最小整数值. dup2函数通过使用参数f

linux下C语言socket网络编程简例

转自:http://blog.csdn.net/kikilizhm/article/details/7858405 这里给出在linux下的简单socket网络编程的实例,使用tcp协议进行通信,服务端进行监听,在收到客户端的连接后,发送数据给客户端:客户端在接受到数据后打印出来,然后关闭.程序里有详细的说明,其中对具体的结构体和函数的实现可以参考其他资料. 程序说明: 这里服务器的端口号和ip地址使用固定的设置,移植时可以根据具体情况更改,可以改写为参数传递更好,这里为了方便,使用固定的. 移

Linux高性能server编程——高级I/O函数

 高级I/O函数 pipe函数 pipe函数用于创建一个管道,实现进程间的通信. #include <unistd.h> int pipe(int pipefd[2]); 通过pipe函数创建的文件描写叙述符fd[0]和fd[1]分别构成管道的两端,往fd[1]写入的数据能够从fd[0]读出,不能反过来.管道内部传输的数据时字节流,和TCP字节流概念同样,但有差别,管道本身拥有一个容量限制,它规定假设应用程序不将数据从管道读走的话,该管道最多能被写入多少字节的数据.管道容量阿东小默认是65

Linux程序设计学习笔记----Socket网络编程基础之TCP/IP协议簇

转载请注明出处: ,谢谢! 内容提要 本节主要学习网络通信基础,主要涉及的内容是: TCP/IP协议簇基础:两个模型 IPv4协议基础:IP地址分类与表示,子网掩码等 IP地址转换:点分十进制\二进制 TCP/IP协议簇基础 OSI模型 我们知道计算机网络之中,有各种各样的设备,那么如何实现这些设备的通信呢? 显然是通过标准的通讯协议,但是,整个网络连接的过程相当复杂,包括硬件.软件数据封包与应用程序的互相链接等等,如果想要写一支将联网全部功能都串连在一块的程序,那么当某个小环节出现问题时,整只

linux 网络编程 socket bind failed 问题解决

今天写一个简单的socket网络通讯的程序的时候,用ctrl+c结束服务器端程序之后,再次启动服务器出现了bind failed:the address already in use的错误.在网上查了一下以后找到了原因,在此记录一下.这个IBM的官网上说到了这一点:http://www.ibm.com/developerworks/cn/linux/l-sockpit/.详细介绍如下: bind 普遍遭遇的问题是试图绑定一个已经在使用的端口.该陷阱是也许没有活动的套接字存在,但仍然禁止绑定端口(

Linux工具开发---2编程实现对输入字符序列变换(编码/加密/散列)方式的智能判定

如何简单实现一个可以智能判定输入字符序列变换方式的小程序 本文由CSDN-蚍蜉撼青松 [主页:http://blog.csdn.net/howeverpf]原创,转载请注明出处! 问题描述: 在分析网络数据包或者研究安全问题时,经常会遇到变换后的字符序列.而能否准确识别密文的变换算法,对进一步的分析工作很关键.常用的变换算法包括但不限于:Base64.URL编码.HTML编码.MD5散列.DES加密.RSA加密等.要求: 1)在理解算法原理及密文特点的基础上,使用任意编程语言实现,当输入一段密文