您的位置:首页 > 理论基础 > 计算机网络

Unix网络编程(一)基本字段和常用函数

2016-03-17 16:11 585 查看
Unix网络编程(一)基本字段和常用函数

1.基本字段

2.常用函数

基本字段

用来表示地址的结构有两个,都是定义在in.h中,分别是sockaddr_in和sockaddr。通常定义并初始化sockaddr_in,在使用函数传递参数时将其强转为后者,因为在大多数函数中,要求的指针类型都sockaddr,然而sockaddr_in的字段较为丰富,容易赋值。

具体的字段定义如下

sockaddr_in

/* Structure describing an Internet socket address.  */
struct sockaddr_in
{
__SOCKADDR_COMMON (sin_);
in_port_t sin_port;         /* Port number.  */
struct in_addr sin_addr;        /* Internet address.  */

/* Pad to size of `struct sockaddr'.  */
unsigned char sin_zero[sizeof (struct sockaddr) -
__SOCKADDR_COMMON_SIZE -
sizeof (in_port_t) -
sizeof (struct in_addr)];
};


sockaddr

/* Structure describing a generic socket address.  */
struct sockaddr
{
__SOCKADDR_COMMON (sa_);    /* Common data: address family and length.  */
char sa_data[14];       /* Address data.  */
};


在这里特别要提的是

第一个字段__SOCKADDR_COMMON 在sockaddr.h中定义为

#define __SOCKADDR_COMMON(sa_prefix) sa_family_t sa_prefix##family


就是以前的sa_family_t类型的名为sin_family的字段。代表着该socket使用的协议族。常用的有AF_INET和AF_INET6,前者代表Ipv4,后者代表Ipv6。

以及sockaddr_in的最后一个字段sin_zero,它是通过计算,让sockaddr_in和sockaddr保持同样的空间大小,保证转换时的完整性。

基本函数

socket()

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


作用:建立一个新的socket

返回值:成功则返回socket对应的代码,失败则为-1

参数:

1.第一个参数指定何种类型的协议族,常用有AF_INET和AF_INET6两种。完整的定义在/usr/include/bits/socket.h 内

2.第二个参数指定类型,常用的是SOCK_STREAM(TCP协议),SOCK_DGRAM(UDP协议)。

3.第三的参数指定传输协议,但因为会自动设置为type参数所对应的协议。因此设置为0即可

connect()

int connect (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len);


作用:将socket 连至参数serv_addr 指定的网络地址

返回值:成功则返回0, 失败返回-1, 错误原因存于errno 中.

参数:

1.第一个是socket

2.第二个是sockaddr的指针

3.第三个是指针的长度(大小)

bind()

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


作用:用于将本地地址与socket捆绑

返回值:成功则返回0, 失败返回-1, 错误原因存于errno 中.

参数:

1.第一个是socket

2.第二个是sockaddr的指针

3.第三个是指针的长度(大小)

listen()

int listen (int __fd, int __n)


作用:监听申请的连接

返回值:正确则返回0。否则的话,返回SOCKET_ERROR错误

参数:

1.第一个为socket的描述符

2.第二个为等待连接队列的最大长度。

accept()

int accept (int __fd, __SOCKADDR_ARG __addr, socklen_t *__restrict __addr_len)


作用:接受来自指定socket的请求,并为该请求分配一个新的描述符

返回值:成功则返回新的socket 处理代码, 失败返回-1, 错误原因存于errno 中.

参数:

1. 第一个参数socket的描述符

2.第二个是sockaddr的指针

3.第三个是指针的长度(大小)

close()

int close (int __fd)


作用:释放对应的文件描述词

返回值:若文件顺利关闭则返回0, 发生错误时返回-1.

参数:

代码

以下是两个例子,

第一个是向13端口请求数据。(13端口是daytime服务的端口,返回所在主机的时间。因此运行时要求开启13端口)。

第二个是模拟daytime服务器,对访问13端口的请求返回主机时间。

请求13端口
#include    <sys/socket.h>  /* basic socket definitions */
#include    <netinet/in.h>

int main()
{
int                 sockfd, n;
char                recvline[MAXLINE + 1];
struct sockaddr_in  servaddr;
char *IPaddress = "127.0.0.1";

if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)    /*创建socket*/
printf("socket error");

bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port   = htons(13);    /* 13端口是daytime服务 */
if (inet_pton(AF_INET, IPaddress, &servaddr.sin_addr) <= 0) /*该函数将字符型表达(presentation)转换位数值(number)*/
printf("inet_pton error for %s", argv[1]);

if (connect(sockfd, (SA *) &servaddr, sizeof(servaddr)) < 0)/*建立连接*/
printf("connect error");

while ( (n = read(sockfd, recvline, MAXLINE)) > 0) {    /*读取流信息*/
recvline
= 0;    /* null terminate */
if (fputs(recvline, stdout) == EOF)
printf("fputs error");
}
if (n < 0)
printf("read error");

exit(0);
}


模拟daytime服务
#include    <sys/socket.h>  /* basic socket definitions */
#include    <netinet/in.h>
#include    <time.h>

int
main(int argc, char **argv)
{
int                 listenfd, connfd;
socklen_t           len;
struct sockaddr_in  servaddr, cliaddr;
char                buff[MAXLINE];
time_t              ticks;

listenfd = Socket(AF_INET, SOCK_STREAM, 0);/*创建socket*/

bzero(&servaddr, sizeof(servaddr));     /*初始化servaddr,将其清空为0.可用memset函数代替,以下三步为其字段赋值*/
servaddr.sin_family      = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);   /*INADDR_ANY为0x00000000 ,意为接收任何来到该地址的请求*/
servaddr.sin_port        = htons(13);

bind(listenfd, (SA *) &servaddr, sizeof(servaddr));     /*将socket与本机指定端口和地址捆绑*/

listen(listenfd, LISTENQ);  /*开启监听*/

for ( ; ; ) {
len = sizeof(cliaddr);
connfd = accept(listenfd, (SA *) &cliaddr, &len); /*当有连接时,将该连接的句柄绑定到connfd上*/
printf("connection from %s, port %d\n",     /*打印请求地址*/
Inet_ntop(AF_INET, &cliaddr.sin_addr, buff, sizeof(buff)),
ntohs(cliaddr.sin_port));

ticks = time(NULL);
snprintf(buff, sizeof(buff), "%.24s\r\n", ctime(&ticks));   /*返回时间*/
write(connfd, buff, strlen(buff));

close(connfd);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: