sockaddr_in , sockaddr , in_addr区别Socket编程函数集(非常有用)

  • Post author:
  • Post category:其他



一、sockaddr和sockaddr_in在字节长度上都为16个BYTE,可以进行转换


struct   sockaddr   {

unsigned   short   sa_family;    //2

char   sa_data[14];     //14

};

上面是通用的socket地址,具体到Internet   socket,用下面的结构,二者可以进行类型转换

struct   sockaddr_in   {

short   int   sin_family;     //2

unsigned   short   int   sin_port;     //2

struct   in_addr   sin_addr;     ‘//4

unsigned   char   sin_zero[8];     //8

};

struct   i


n_addr就是32位IP地址。





struct   in_addr   {



union {




struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b;



struct { u_short s_w1,s_w2; } S_un_w;



u_long S_addr;



} S_un;


#define s_addr  S_un.S_addr

};


或者;


struct in_addr {


in_addr_t s_addr;

};

结构体in_addr 用来表示一个32位的IPv4地址



inet_addr()是将一个点分制的IP地址(如192.168.0.1)转换为上述结构中需要的32位二进制方式的IP地址(0xC0A80001)。//server_addr.sin_addr.s_addr=htonl(INADDR_ANY);


通常的做法是





填值的时候使用sockaddr_in结构





而作为函数(如bin, accept, connect等)的参数传入的时候转换成sockaddr结构就行了,毕竟都是16个字符长。


通常的用法是:

int   sockfd;

struct   sockaddr_in   my_addr;


//赋值时用这个结构



sockfd   =   socket(AF_INET,   SOCK_STREAM,   0);



my_addr.sin_family   =   AF_INET;



my_addr.sin_port   =   htons(MYPORT);



my_addr.sin_addr.s_addr   =   inet_addr(“192.168.0.1”);



bzero(&(my_addr.sin_zero),   8);



bind(sockfd,   (struct   sockaddr   *)&my_addr,   sizeof(struct   sockaddr));


//用

(struct   sockaddr   *)转换即满足要求



//


int accept(int s,struct sockaddr * addr,int * addrlen);//这三个函数的第二个参数结构都为struct sockaddr,所以一般做法都如上所示。




//



int bind(int sockfd,struct sockaddr * my_addr,int addrlen);





//int connect (int sockfd,struct sockaddr * serv_addr,int addrlen);






二 、说个小知识,为什么一般情况下都用

serv.sin_addr.s_addr=htonl(INADDR_ANY)





比如你的机器有三个ip




192.168.1.1




202.202.202.202




61.1.2.3








如果你serv.sin_addr.s_addr=inet_addr(“192.168.1.1”);








然后监听100端口








这时其他机器只有connect   192.168.1.1:100端口才能成功。




connect   202.202.202.202:100和connect   61.1.2.3:100都会失败。








如果serv.sin_addr.s_addr=htonl(INADDR_ANY);   的话,无论连接哪个ip都可以连上的,这就是为什么这样选择的理由












三、另外一个关于这连个结构的一个解释,觉得也还不错。






struct sockaddr 是一个通用地址结构,这是为了统一地址结构的表示方法,统一接口函数,使不同的地址结构可以被bind() , connect() 等函数调用;


struct sockaddr_in中的in 表示internet,就是网络地址


,这只是我们比较常用的地址结构,属于AF_INET地址族,他非常的常用,以至于我们都开始讨论它与 struct sockaddr通用地址结构的区别。另外还有struct sockaddr_un 地址结构,剩下的地址结构我就不知道了。我们可以认为 struct sockaddr_in 和 struct sockaddr_un 是 struct sockaddr 的子集。

struct sockaddr {




unsigned short sa_family; /* address family, AF_xxx */



char sa_data[14]; /* 14 bytes of protocol address */



};


里的sa_data里的IP地址取出来,折腾半天还是失败了。在CSDN上发现2003年时曾有人跟我一样傻 哈哈


struct sockaddr {




unsigned short sa_family; /* address family, AF_xxx */



char sa_data[14]; /* 14 bytes of protocol address */



};



sa_family是地址家族,一般都是“AF_xxx”的形式。好像通常大多用的是都是AF_INET。



sa_data是14字节协议地址。



此数据结构用做bind、connect、recvfrom、sendto等函数的参数,指明地址信息。



但一般编程中并不直接针对此数据结构操作,而是使用另一个与sockaddr等价的数据结构



sockaddr_in(在netinet/in.h中定义):



struct sockaddr_in {




short int sin_family; /* Address family */



unsigned short int sin_port; /* Port number */



struct in_addr sin_addr; /* Internet address */



unsigned char sin_zero[8]; /* Same size as struct sockaddr */



};



struct in_addr {




unsigned long s_addr;



};



typedef struct in_addr {




union {




struct{




unsigned char s_b1,



s_b2,



s_b3,



s_b4;



} S_un_b;



struct {




unsigned short s_w1,



s_w2;



} S_un_w;



unsigned long S_addr;



} S_un;



} IN_ADDR;



sin_family指代协议族,在socket编程中只能是AF_INET



sin_port存储端口号(使用网络字节顺序)



sin_addr存储IP地址,使用in_addr这个数据结构



sin_zero是为了让sockaddr与sockaddr_in两个数据结构保持大小相同而保留的空字节。



s_addr按照网络字节顺序存储IP地址



sockaddr_in和sockaddr是并列的结构,指向sockaddr_in的结构体的指针也可以指向



sockadd的结构体,并代替它。也就是说,你可以使用sockaddr_in建立你所需要的信息,



在最后用进行类型转换就可以了bzero((char*)&mysock,sizeof(mysock));//初始化



mysock结构体名



mysock.sa_family=AF_INET;



mysock.sin_addr.s_addr=inet_addr(“192.168.0.1”);



……



等到要做转换的时候用:



(struct sockaddr*)mysock




四、备注常用的socket函数集:









accept


(接受


socket


连线)


相关函数

socket





bind





listen





connect

表头文件

#include<sys/types.h>

#include<sys/socket.h>

定义函数


int accept(int s,struct sockaddr * addr,int * addrlen);


函数说明

accept()


用来接受参数


s





socket


连线。参数


s





socket


必需先经


bind()





listen()


函数处理过,当有连线进来时


accept()


会返回一个新的


socket


处理代码,往后的数据传送与读取就是经由新的


socket


处理,而原来参数


s





socket


能继续使用


accept()


来接受新的连线要求。连线成功时,参数


addr


所指的结构会被系统填入远程主机的地址数据,参数


addrlen





scokaddr


的结构长度。关于结构


sockaddr


的定义请参考


bind()




返回值

成功则返回新的


socket


处理代码,失败返回


-1


,错误原因存于


errno


中。

错误代码


EBADF



参数


s


非合法


socket


处理代码。


EFAULT



参数


addr


指针指向无法存取的内存空间。


ENOTSOCK



参数


s


为一文件描述词,非


socket





EOPNOTSUPP



指定的


socket


并非


SOCK_STREAM





EPERM



防火墙拒绝此连线。


ENOBUFS



系统的缓冲内存不足。


ENOMEM



核心内存不足。

范例

参考


listen()





bind


(对


socket


定位)


相关函数

socket





accept





connect





listen

表头文件

#include<sys/types.h>

#include<sys/socket.h>

定义函数


int bind(int sockfd,struct sockaddr * my_addr,int addrlen);


函数说明

bind()


用来设置给参数


sockfd





socket


一个名称。此名称由参数


my_addr


指向一


sockaddr


结构,对于不同的


socket domain


定义了一个通用的数据结构。

struct sockaddr {


unsigned short int sa_family;

char sa_data[14];

};

sa_family


为调用


socket


()时的


domain


参数,即


AF_xxxx


值。

sa_data


最多使用


14


个字符长度。




sockaddr


结构会因使用不同的


socket domain


而有不同结构定义,例如使用


AF_INET domain


,其


socketaddr


结构定义便为

struct socketaddr_in {


unsigned short int sin_family;

uint16_t sin_port;

struct in_addr sin_addr;

unsigned char sin_zero[8];

};

struct in_addr {


uint32_t s_addr;

};

sin_family


即为


sa_family

sin_port


为使用的


port


编号

sin_addr.s_addr





IP


地址

sin_zero


未使用。

参数说明

addrlen





sockaddr


的结构长度。

返回值

成功则返回


0


,失败返回


-1


,错误原因存于


errno


中。

错误代码


EBADF



参数


sockfd


非合法


socket


处理代码。


EACCESS



权限不足


ENOTSOCK



参数


sockfd


为一文件描述词,非


socket




范例

参考


listen()


connect


(建立


socket


连线)


相关函数

socket





bind





listen

表头文件

#include<sys/types.h>

#include<sys/socket.h>

定义函数


int connect (int sockfd,struct sockaddr * serv_addr,int addrlen);


函数说明

connect()


用来将参数


sockfd





socket


连至参数


serv_addr


指定的网络地址。结构


sockaddr


请参考


bind()


。参数


addrlen





sockaddr


的结构长度。

返回值

成功则返回


0


,失败返回


-1


,错误原因存于


errno


中。

错误代码


EBADF



参数


sockfd


非合法


socket


处理代码


EFAULT



参数


serv_addr


指针指向无法存取的内存空间


ENOTSOCK



参数


sockfd


为一文件描述词,非


socket





EISCONN



参数


sockfd





socket


已是连线状态


ECONNREFUSED



连线要求被


server


端拒绝。


ETIMEDOUT



企图连线的操作超过限定时间仍未有响应。


ENETUNREACH



无法传送数据包至指定的主机。


EAFNOSUPPORT



sockaddr


结构的


sa_family


不正确。


EALREADY



socket


为不可阻断且先前的连线操作还未完成。

范例

/*


利用


socket





TCP client

*


此程序会连线


TCP server


,并将键盘输入的字符串传送给


server




* TCP server


范例请参考


listen


()。

*/

#include<sys/stat.h>

#include<fcntl.h>

#include<unistd.h>

#include<sys/types.h>

#include<sys/socket.h>

#include<netinet/in.h>

#include<arpa/inet.h>

#define PORT 1234

#define SERVER_IP “127.0.0.1”

main()

{


int s;

struct sockaddr_in addr;

char buffer[256];

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

{


perror(“socket”);

exit(1);

}

/*


填写


sockaddr_in


结构


*/

bzero(&addr,sizeof(addr));

addr.sin_family = AF_INET;

addr.sin_port = htons(PORT);

addr.sin_addr.s_addr = inet_addr(SERVER_IP); /*


尝试连线


*/

if (connect(s,&addr,sizeof(addr))<0)

{


perror(“connect”);

exit(1);

}

/*


接收由


server


端传来的信息


*/

recv(s,buffer,sizeof(buffer),0);

printf(“%s\n”,buffer);

while(1)

{


bzero(buffer, sizeof(buffer));

/*


从标准输入设备取得字符串


*/

read(STDIN_FILENO, buffer, sizeof(buffer));

/*


将字符串传给


server





*/

if (send(s, buffer, sizeof(buffer), 0)<0)

{


perror(“send”);

exit(1);

}

}

}

执行

$ ./connect

Welcome to server!

hi I am client! /*


键盘输入


*/

/*<Ctrl+C>


中断程序


*/


endprotoent


(结束网络协议数据的读取)


相关函数

getprotoent





getprotobyname





getprotobynumber





setprotoent

表头文件

#include<netdb.h>

定义函数


void endprotoent(void);


函数说明

endprotoent()


用来关闭由


getprotoent()


打开的文件。

返回值

无返回值

范例

参考


getprotoent()


endservent


(结束网络服务数据的读取)


相关函数

getservent





getservbyname





getservbyport





setservent

表头文件

#include<netdb.h>

定义函数


void endservent(void);


函数说明

endservent()


用来关闭由


getservent()


所打开的文件。

返回值

无返回值

范例

参考


getservent()





getsockopt


(取得


socket


状态)


相关函数

setsockopt

表头文件

#include<sys/types.h>

#include<sys/socket.h>

定义函数


int getsockopt(int s,int level,int optname,void* optval,socklen_t* optlen);


函数说明

getsockopt()


会将参数


s


所指定的


socket


状态返回。参数


optname


代表欲取得何种选项状态,而参数


optval


则指向欲保存结果的内存地址,参数


optlen


则为该空间的大小。参数


level





optname


请参考


setsockopt()




返回值

成功则返回


0


,若有错误则返回


-1


,错误原因存于


errno

错误代码


EBADF



参数


s


并非合法的


socket


处理代码


ENOTSOCK



参数


s


为一文件描述词,非


socket


ENOPROTOOPT



参数


optname


指定的选项不正确


EFAULT



参数


optval


指针指向无法存取的内存空间

范例

#include<sys/types.h>

#include<sys/socket.h>

main()

{


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

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

perror(“socket”);

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

printf(“optval = %d\n”,optval);

close(s);

}

执行

optval = 1 /*SOCK_STREAM


的定义正是此值


*/



htonl


(将


32


位主机字符顺序转换成网络字符顺序)



相关函数

htons





ntohl





ntohs

表头文件

#include<netinet/in.h>

定义函数


unsigned long int htonl(unsigned long int hostlong);


函数说明

Htonl()


用来将参数指定的


32





hostlong


转换成网络字符顺序。

返回值

返回对应的网络字符顺序。

范例

参考


getservbyport()





connect()






htons


(将


16


位主机字符顺序转换成网络字符顺序)



相关函数

htonl





ntohl





ntohs

表头文件

#include<netinet/in.h>

定义函数


unsigned short int htons(unsigned short int hostshort);


函数说明

htons()


用来将参数指定的


16





hostshort


转换成网络字符顺序。

返回值

返回对应的网络字符顺序。

范例

参考


connect()





inet_addr


(将网络地址转成二进制的数字)


相关函数

inet_aton





inet_ntoa

表头文件

#include<sys/socket.h>

#include<netinet/in.h>

#include<arpa/inet.h>

定义函数

unsigned long int inet_addr(const char *cp);

函数说明

inet_addr()


用来将参数


cp


所指的网络地址字符串转换成网络所使用的二进制数字。网络地址字符串是以数字和点组成的字符串,例如


:“163.13.132.68”




返回值

成功则返回对应的网络二进制的数字,失败返回


-1





inet_aton


(将网络地址转成网络二进制的数字)


相关函数

inet_addr





inet_ntoa

表头文件

#include<sys/scoket.h>

#include<netinet/in.h>

#include<arpa/inet.h>

定义函数


int inet_aton(const char * cp,struct in_addr *inp);


函数说明

inet_aton()


用来将参数


cp


所指的网络地址字符串转换成网络使用的二进制的数字,然后存于参数


inp


所指的


in_addr


结构中。

结构


in_addr


定义如下

struct in_addr {


unsigned long int s_addr;

};

返回值

成功则返回非


0


值,失败则返回


0






inet_ntoa


(将网络二进制的数字转换成网络地址)



相关函数

inet_addr





inet_aton

表头文件

#include<sys/socket.h>

#include<netinet/in.h>

#include<arpa/inet.h>

定义函数


char * inet_ntoa(struct in_addr in);


函数说明

inet_ntoa()


用来将参数


in


所指的网络二进制的数字转换成网络地址,然后将指向此网络地址字符串的指针返回。

返回值

成功则返回字符串指针,失败则返回


NULL





listen


(等待连接)


相关函数

socket





bind





accept





connect

表头文件

#include<sys/socket.h>

定义函数


int listen(int s,int backlog);


函数说明

listen()


用来等待参数


s





socket


连线。参数


backlog


指定同时能处理的最大连接要求,如果连接数目达此上限则


client


端将收到


ECONNREFUSED


的错误。


Listen()


并未开始接收连线,只是设置


socket





listen


模式,真正接收


client


端连线的是


accept()


。通常


listen()


会在


socket()





bind()


之后调用,接着才调用


accept()




返回值

成功则返回


0


,失败返回


-1


,错误原因存于


errno

附加说明

listen()


只适用


SOCK_STREAM





SOCK_SEQPACKET





socket


类型。如果


socket





AF_INET


则参数


backlog


最大值可设至


128




错误代码


EBADF



参数


sockfd


非合法


socket


处理代码


EACCESS



权限不足


EOPNOTSUPP



指定的


socket


并未支援


listen


模式。

范例

#include<sys/types.h>

#include<sys/socket.h>

#include<netinet/in.h>

#include<arpa/inet.h>

#include<unistd.h>

#define PORT 1234

#define MAXSOCKFD 10

main()

{


int sockfd,newsockfd,is_connected[MAXSOCKFD],fd;

struct sockaddr_in addr;

int addr_len = sizeof(struct sockaddr_in);

fd_set readfds;

char buffer[256];

char msg[ ] =”Welcome to server!”;

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

{


perror(“socket”);

exit(1);

}

bzero(&addr,sizeof(addr));

addr.sin_family =AF_INET;

addr.sin_port = htons(PORT);

addr.sin_addr.s_addr = htonl(INADDR_ANY);

if (bind(sockfd,&addr,sizeof(addr))<0)

{


perror(“connect”);

exit(1);

}

if (listen(sockfd,3)<0)

{


perror(“listen”);

exit(1);

}

for (fd=0; fd<MAXSOCKFD; fd++)

is_connected[fd]=0;

while(1)

{


FD_ZERO(&readfds);

FD_SET(sockfd,&readfds);

for (fd=0; fd<MAXSOCKFD; fd++)

if (is_connected[fd])

FD_SET(fd,&readfds);

if (!select(MAXSOCKFD, &readfds, NULL, NULL, NULL))

continue;

for (fd=0;fd<MAXSOCKFD;fd++)

if (FD_ISSET(fd,&readfds))

{


if (sockfd = =fd)

{


if((newsockfd = accept (sockfd,&addr,&addr_len))<0)

perror(“accept”);

write(newsockfd,msg,sizeof(msg));

is_connected[newsockfd] =1;

printf(“cnnect from %s\n”,

inet_ntoa

(addr.sin_addr));

//获取客户端IP地址


}

else

{


bzero(buffer, sizeof(buffer));

if (read(fd,buffer,sizeof(buffer))<=0)

{


printf(“connect closed.\n”);

is_connected[fd]=0;

close(fd);

}

else

printf(“%s”,buffer);

}

}

}

}

执行

$ ./listen

connect from 127.0.0.1

hi I am client

connected closed.


ntohl


(将


32


位网络字符顺序转换成主机字符顺序)


相关函数

htonl





htons





ntohs

表头文件

#include<netinet/in.h>

定义函数


unsigned long int ntohl(unsigned long int netlong);


函数说明

ntohl()


用来将参数指定的


32





netlong


转换成主机字符顺序。

返回值

返回对应的主机字符顺序。

范例

参考


getservent()





ntohs


(将


16


位网络字符顺序转换成主机字符顺序)


相关函数

htonl





htons





ntohl

表头文件

#include<netinet/in.h>

定义函数


unsigned short int ntohs(unsigned short int netshort);


函数说明

ntohs()


用来将参数指定的


16





netshort


转换成主机字符顺序。

返回值

返回对应的主机顺序。

范例

参考


getservent()





recv


(经


socket


接收数据)


相关函数

recvfrom





recvmsg





send





sendto





socket

表头文件

#include<sys/types.h>

#include<sys/socket.h>

定义函数


int recv(int s,void *buf, int len, unsigned int flags);


函数说明

recv()


用来接收远端主机经指定的


socket


传来的数据,并把数据存到由参数


buf


指向的内存空间,参数


len


为可接收数据的最大长度。

参数



返回值

flags


一般设


0


。其他数值定义如下


:


MSG_OOB



接收以


out-of-band


送出的数据。


MSG_PEEK



返回来的数据并不会在系统内删除,如果再调用


recv()


会返回相同的数据内容。


MSG_WAITALL



强迫接收到


len


大小的数据后才能返回,除非有错误或信号产生。


MSG_NOSIGNAL



此操作不愿被


SIGPIPE


信号中断返回值成功则返回接收到的字符数,失败返回


-1


,错误原因存于


errno


中。

错误代码


EBADF



参数


s


非合法的


socket


处理代码


FAULT



参数中有一指针指向无法存取的内存空间


ENOTSOCK



参数


s


为一文件描述词,非


socket





EINTR



被信号所中断


EAGAIN



此动作会令进程阻断,但参数


s





socket


为不可阻断


ENOBUFS



系统的缓冲内存不足。


ENOMEM



核心内存不足


EINVAL



传给系统调用的参数不正确。

范例

参考


listen()





recvfrom


(经


socket


接收数据)


相关函数

recv





recvmsg





send





sendto





socket

表头文件

#include<sys/types.h>

#include<sys/socket.h>

定义函数


int recvfrom(int s,void *buf,int len,unsigned int flags ,struct sockaddr *from ,int *fromlen);


函数说明

recv()


用来接收远程主机经指定的


socket


传来的数据,并把数据存到由参数


buf


指向的内存空间,参数


len


为可接收数据的最大长度。参数


flags


一般设


0


,其他数值定义请参考


recv()


。参数


from


用来指定欲传送的网络地址,结构


sockaddr


请参考


bind()


。参数


fromlen





sockaddr


的结构长度。

返回值

成功则返回接收到的字符数,失败则返回


-1


,错误原因存于


errno


中。

错误代码


EBADF



参数


s


非合法的


socket


处理代码


EFAULT



参数中有一指针指向无法存取的内存空间。


ENOTSOCK



参数


s


为一文件描述词,非


socket





EINTR



被信号所中断。


EAGAIN



此动作会令进程阻断,但参数


s





socket


为不可阻断。


ENOBUFS



系统的缓冲内存不足


ENOMEM



核心内存不足


EINVAL



传给系统调用的参数不正确。

范例

/*


利用


socket





UDP client

*


此程序会连线


UDP server


,并将键盘输入的字符串传给


server




* UDP server


范例请参考


sendto


()。

*/

#include<sys/stat.h>

#include<fcntl.h>

#include<unistd.h>

#include<sys/typs.h>

#include<sys/socket.h>

#include<netinet/in.h>

#include<arpa/inet.h>

#define PORT 2345

#define SERVER_IP “127.0.0.1”

main()

{


int s,len;

struct sockaddr_in addr;

int addr_len =sizeof(struct sockaddr_in);

char buffer[256];

/*


建立


socket*/

if ((s = socket(AF_INET,SOCK_DGRAM,0))<0)

{


perror(“socket”);

exit(1);

}

/*


填写


sockaddr_in*/

bzero(&addr,sizeof(addr));

addr.sin_family = AF_INET;

addr.sin_port = htons(PORT);

addr.sin_addr.s_addr = inet_addr(SERVER_IP);

while(1)

{


bzero(buffer,sizeof(buffer));

/*


从标准输入设备取得字符串


*/

len =read(STDIN_FILENO,buffer,sizeof(buffer));

/*


将字符串传送给


server





*/

sendto(s,buffer,len,0,&addr,addr_len);

/*


接收


server


端返回的字符串


*/

len = recvfrom(s,buffer,sizeof(buffer),0,&addr,&addr_len);

printf(“receive: %s”,buffer);

}

}

执行

(


先执行


udp server


再执行


udp client)

hello /*


从键盘输入字符串


*/

receive: hello /*server


端返回来的字符串


*/


recvmsg


(经


socket


接收数据)


相关函数

recv





recvfrom





send





sendto





sendmsg





socket

表头文件

#include<sys/types.h>

#include<sys/socktet.h>

定义函数


int recvmsg(int s,struct msghdr *msg,unsigned int flags);


函数说明

recvmsg()


用来接收远程主机经指定的


socket


传来的数据。参数


s


为已建立好连线的


socket


,如果利用


UDP


协议则不需经过连线操作。参数


msg


指向欲连线的数据结构内容,参数


flags


一般设


0


,详细描述请参考


send()


。关于结构


msghdr


的定义请参考


sendmsg()




返回值

成功则返回接收到的字符数,失败则返回


-1


,错误原因存于


errno


中。

错误代码


EBADF



参数


s


非合法的


socket


处理代码。


EFAULT



参数中有一指针指向无法存取的内存空间


ENOTSOCK



参数


s


为一文件描述词,非


socket





EINTR



被信号所中断。


EAGAIN



此操作会令进程阻断,但参数


s





socket


为不可阻断。


ENOBUFS



系统的缓冲内存不足


ENOMEM



核心内存不足


EINVAL



传给系统调用的参数不正确。

范例

参考


recvfrom()





send


(经


socket


传送数据)


相关函数

sendto





sendmsg





recv





recvfrom





socket

表头文件

#include<sys/types.h>

#include<sys/socket.h>

定义函数


int send(int s,const void * msg,int len,unsigned int falgs);


函数说明

send()


用来将数据由指定的


socket


传给对方主机。参数


s


为已建立好连接的


socket


。参数


msg


指向欲连线的数据内容,参数


len


则为数据长度。参数


flags


一般设


0


,其他数值定义如下





MSG_OOB



传送的数据以


out-of-band


送出。


MSG_DONTROUTE



取消路由表查询


MSG_DONTWAIT



设置为不可阻断运作


MSG_NOSIGNAL



此动作不愿被


SIGPIPE


信号中断。

返回值

成功则返回实际传送出去的字符数,失败返回


-1


。错误原因存于


errno

错误代码


EBADF



参数


s


非合法的


socket


处理代码。


EFAULT



参数中有一指针指向无法存取的内存空间


ENOTSOCK



参数


s


为一文件描述词,非


socket





EINTR



被信号所中断。


EAGAIN



此操作会令进程阻断,但参数


s





socket


为不可阻断。


ENOBUFS



系统的缓冲内存不足


ENOMEM



核心内存不足


EINVAL



传给系统调用的参数不正确。

范例

参考


connect()


sendmsg


(经


socket


传送数据)


相关函数

send





sendto





recv





recvfrom





recvmsg





socket

表头文件

#include<sys/types.h>

#include<sys/socket.h>

定义函数


int sendmsg(int s,const strcut msghdr *msg,unsigned int flags);


函数说明

sendmsg()


用来将数据由指定的


socket


传给对方主机。参数


s


为已建立好连线的


socket


,如果利用


UDP


协议则不需经过连线操作。参数


msg


指向欲连线的数据结构内容,参数


flags


一般默认为


0


,详细描述请参考


send()




结构


msghdr


定义如下

struct msghdr {


void *msg_name; /*Address to send to /receive from . */

socklen_t msg_namelen; /* Length of addres data */

strcut iovec * msg_iov; /* Vector of data to send/receive into */

size_t msg_iovlen; /* Number of elements in the vector */

void * msg_control; /* Ancillary dat */

size_t msg_controllen; /* Ancillary data buffer length */

int msg_flags; /* Flags on received message */

};

返回值

成功则返回实际传送出去的字符数,失败返回


-1


,错误原因存于


errno

错误代码


EBADF



参数


s


非合法的


socket


处理代码。


EFAULT



参数中有一指针指向无法存取的内存空间


ENOTSOCK



参数


s


为一文件描述词,非


socket





EINTR



被信号所中断。


EAGAIN



此操作会令进程阻断,但参数


s





socket


为不可阻断。


ENOBUFS



系统的缓冲内存不足


ENOMEM



核心内存不足


EINVAL



传给系统调用的参数不正确。

范例

参考


sendto()





sendto


(经


socket


传送数据)


相关函数

send , sendmsg,recv , recvfrom , socket

表头文件

#include < sys/types.h >

#include < sys/socket.h >

定义函数


int sendto ( int s , const void * msg, int len, unsigned int flags, const struct sockaddr * to , int tolen ) ;


函数说明

sendto()


用来将数据由指定的


socket


传给对方主机。参数


s


为已建好连线的


socket,


如果利用


UDP


协议则不需经过连线操作。参数


msg


指向欲连线的数据内容,参数


flags


一般设


0


,详细描述请参考


send()


。参数


to


用来指定欲传送的网络地址,结构


sockaddr


请参考


bind()


。参数


tolen





sockaddr


的结果长度。

返回值

成功则返回实际传送出去的字符数,失败返回-


1


,错误原因存于


errno


中。

错误代码


EBADF



参数


s


非法的


socket


处理代码。


EFAULT



参数中有一指针指向无法存取的内存空间。


WNOTSOCK



canshu s


为一文件描述词,非


socket





EINTR



被信号所中断。


EAGAIN



此动作会令进程阻断,但参数


s





soket


为补课阻断的。


ENOBUFS



系统的缓冲内存不足。


EINVAL



传给系统调用的参数不正确。

范例

#include < sys/types.h >

#include < sys/socket.h >

# include <netinet.in.h>

#include <arpa.inet.h>

#define PORT 2345 /*


使用的


port*/

main()

{


int sockfd,len;

struct sockaddr_in addr;

char buffer[256];

/*


建立


socket*/

if (sockfd=socket (AF_INET,SOCK_DGRAM,0))<0}

{


perror (“socket”);

exit(1);

}

/*


填写


sockaddr_in


结构


*/

bzero ( &addr, sizeof(addr) );

addr.sin_family=AF_INET;

addr.sin_port=htons(PORT);

addr.sin_addr=hton1(INADDR_ANY) ;

if (bind(sockfd, &addr, sizeof(addr))<0)

{


perror(“connect”);

exit(1);

}

while(1)

{


bezro(buffer,sizeof(buffer));

len = recvfrom(socket,buffer,sizeof(buffer), 0 , &addr &addr_len);

/*


显示


client


端的网络地址


*/

printf(“receive from %s\n “ , inet_ntoa( addr.sin_addr));

/*


将字串返回给


client





*/

sendto(sockfd,buffer,len,0,&addr,addr_len);”

}

}

执行

请参考


recvfrom()


setprotoent


(打开网络协议的数据文件)


相关函数

getprotobyname, getprotobynumber, endprotoent

表头文件

#include <netdb.h>

定义函数


void setprotoent (int stayopen);


函数说明

setprotoent()


用来打开


/etc/protocols





如果参数


stayopen


值为


1


,则接下来的


getprotobyname()





getprotobynumber()


将不会自动关闭此文件。


setservent


(打开主机网络服务的数据文件)


相关函数

getservent, getservbyname, getservbyport, endservent

表头文件

#include < netdb.h >

定义函数


void setservent (int stayopen);


函数说明

setservent()


用来打开


/etc/services


,如果参数


stayopen


值为


1


,则接下来的


getservbyname()





getservbyport()


将补回自动关闭文件。


setsockopt


(设置


socket


状态)


相关函数

getsockopt

表头文件

#include<sys/types.h>

#include<sys/socket.h>

定义函数


int setsockopt(int s,int level,int optname,const void * optval,,socklen_toptlen);


函数说明

setsockopt()


用来设置参数


s


所指定的


socket


状态。参数


level


代表欲设置的网络层,一般设成


SOL_SOCKET


以存取


socket


层。参数


optname


代表欲设置的选项,有下列几种数值


:


SO_DEBUG



打开或关闭排错模式


SO_REUSEADDR



允许在


bind


()过程中本地地址可重复使用


SO_TYPE



返回


socket


形态。


SO_ERROR



返回


socket


已发生的错误原因


SO_DONTROUTE



送出的数据包不要利用路由设备来传输。


SO_BROADCAST



使用广播方式传送


SO_SNDBUF



设置送出的暂存区大小


SO_RCVBUF



设置接收的暂存区大小


SO_KEEPALIVE



定期确定连线是否已终止。


SO_OOBINLINE



当接收到


OOB


数据时会马上送至标准输入设备


SO_LINGER



确保数据安全且可靠的传送出去。

参数

optval


代表欲设置的值,参数


optlen


则为


optval


的长度。

返回值

成功则返回


0


,若有错误则返回


-1


,错误原因存于


errno




附加说明


EBADF



参数


s


并非合法的


socket


处理代码。


ENOTSOCK



参数


s


为一文件描述词,非


socket





ENOPROTOOPT



参数


optname


指定的选项不正确。


EFAULT



参数


optval


指针指向无法存取的内存空间。

范例

参考


getsockopt()





shutdown


(终止


socket


通信)


相关函数

socket





connect

表头文件

#include<sys/socket.h>

定义函数


int shutdown(int s,int how);


函数说明

shutdown()


用来终止参数


s


所指定的


socket


连线。参数


s


是连线中的


socket


处理代码,参数


how


有下列几种情况


:

how=0


终止读取操作。

how=1


终止传送操作

how=2


终止读取及传送操作

返回值

成功则返回


0


,失败返回


-1


,错误原因存于


errno




错误代码


EBADF



参数


s


不是有效的


socket


处理代码。


ENOTSOCK



参数


s


为一文件描述词,非


socket





ENOTCONN



参数


s


指定的


socket


并未连线。


socket


(建立一个


socket


通信)


相关函数

accept





bind





connect





listen

表头文件

#include<sys/types.h>

#include<sys/socket.h>

定义函数


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


函数说明

socket()


用来建立一个新的


socket


,也就是向系统注册,通知系统建立一通信端口。参数


domain


指定使用何种的地址类型,完整的定义在


/usr/include/bits/socket.h


内,底下是常见的协议


:


PF_UNIX/PF_LOCAL/AF_UNIX/AF_LOCAL



UNIX


进程通信协议。


PF_INET?AF_INET



Ipv4


网络协议。


PF_INET6/AF_INET6



Ipv6


网络协议。


PF_IPX/AF_IPX



IPX-Novell


协议。


PF_NETLINK/AF_NETLINK



核心用户接口装置。


PF_X25/AF_X25



ITU-T X.25/ISO-8208


协议。


PF_AX25/AF_AX25



业余无线


AX.25


协议。


PF_ATMPVC/AF_ATMPVC



存取原始


ATM PVCs





PF_APPLETALK/AF_APPLETALK



appletalk





DDP


)协议。


PF_PACKET/AF_PACKET



初级封包接口

参数

type


有下列几种数值


:


SOCK_STREAM



提供双向连续且可信赖的数据流,即


TCP


。支持

OOB


机制,在所有数据传送前必须使用


connect()


来建立连线状态。


SOCK_DGRAM



使用不连续不可信赖的数据包连接


SOCK_SEQPACKET



提供连续可信赖的数据包连接


SOCK_RAW



提供原始网络协议存取


SOCK_RDM



提供可信赖的数据包连接


SOCK_PACKET



提供和网络驱动程序直接通信。

protocol


用来指定


socket


所使用的传输协议编号,通常此参考不用管它,设

返回值

成功则返回


socket


处理代码,失败返回


-1




错误代码


EPROTONOSUPPORT



参数


domain


指定的类型不支持参数


type





protocol


指定的协议


ENFILE



核心内存不足,无法建立新的


socket


结构;


EMFILE



进程文件表溢出,无法再建立新的


socket


EACCESS



权限不足,无法建立


type





protocol


指定的协议


ENOBUFS



/

ENOMEM



内存不足


EINVAL



参数


domain/type/protocol


不合法

范例

参考


connect()

















版权声明:本文为maopig原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。