Chinaunix首页 | 论坛 | 博客
  • 博客访问: 249801
  • 博文数量: 51
  • 博客积分: 1410
  • 博客等级: 上尉
  • 技术积分: 575
  • 用 户 组: 普通用户
  • 注册时间: 2006-09-22 13:49
文章分类
文章存档

2009年(1)

2008年(13)

2007年(7)

2006年(30)

我的朋友

分类:

2007-01-14 16:03:38

1、htonl, htons, ntohl, ntohs

它们均在在arpa/inet.h中声明。
作用:把主机(网络)字节顺序的数据以长整型(短整型)转换为网络(主机)字节顺序的数据。输入参数为相应的主机(网络)字节顺序的长整型(短整型)值,返回网络(主机)字节顺序的长整型(短整型)值。
网络编程,需要注意相关的调用返回值是主机字节顺序还是网络字节顺序,是否需要进行转换,以提高源代码的健壮性和可移植性。

2、gethostbyname, gethostbyaddr, getprotobyname, getprotobynumber, getsservbyname, getservbyport

引用他们的方法均为:

#include <netdb.h>


struct hostent *gethostbyname(const char *name):输入主机名字或者IP地址,按网络字节顺序返回一个hostent结构。
struct hostent *gethostbyaddr(struct *addr, int len, int type):输入程度为len,类型为type的主机名字或者网络地址,按网络字节顺序返回一个hostent结构,类型包括AF_INET和AF_INET6。

struct protoent *getprotobyname(const char *name):输入协议名字name,返回匹配的protoent结构。可以使用的协议名字可以参考/etc/protocols每行的第一个字段。
struct protoent *getprotobynumber(int protocol):输入协议号protocol,返回匹配的protoent结构。可以使用的协议号可以参考/etc/protocols每行的第二个字段。

struct servent *getservbyname(const char *name, const char *proto):输入使用协议proto的服务名name,返回匹配的servent结构。可以使用的服务名参考/etc/service每行的第一个字段,而proto为/etc/protocol。如果不指定协议,则匹配任何协议。
struct servent *getservbyport(int port, const char *proto):输入使用协议proto的端口port,返回servent结构。如果不指定协议,则匹配任何协议。

以上的返回值都是网络字节顺序。

3、socket套接口最基本的相关调用

Linux socket编程的相关函数都通过引用sys/socket.h来进行调用,可能还需要包括sys/types.h。

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


socket调用:为互联通信建立一个端点,以套接字描述符标识。
domain包括了AF_UNIX, AF_INET, AF_IPX等,其中最常用的
是AF_INET;
另外,在man socket中,给出的域类型是PF_*开头的,由于在各种系统的TCP/IP实现中,协议族和地址族是一一对应的,所以它和AF_*在头文件定义中是等价的。
type包括了SOCK_STREAM, SOCK_DGRAM及其它。
protocol一般可以设置为0。
socket调用成功,返回一个整型的套接口描述符。


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


bind调用:把一个长度为addrlen的sockaddr结构与套接口描述符sockfd绑定,sockfd一般通过socket调用返回的值获得。
sockaddr结构用于保存了套接字地址族结构的相关信息,它的定义为:

struct sockaddr{
        sa_family_t sa_family;
        char sa_data[14];
}



int listen(int sockfd, int backlog);


listen调用一般在作为服务器时,用于监听指定套接字的接入请求,并分配等待队列的长度为backlog。

int accept(int socket, struct sockaddr *restrict_address, socklen_t *restrict address_len);


accept调用检索listen的队列中挂起的某个接入要求并处理之,输入监听套接口的套接口描述符socket,以及接入信息所使用的缓冲区restrict_address及其能容纳的大小address_len。

int connect (int socket, const struct sockaddr *address, socklen_t address_len);


connect调用在套接字socket上建立起一个连接,使用一个sockaddr结构address的缓冲区接收远程对等端的相应结构(它已经和远程的一个socket绑定),它的长度为address_len。缓冲区address在使用之前最好用bzero函数清零,此函数位于string.h。


ssize_t recv(int socket, void *buffer, size_t length, int flags);


recv调用接收已经建立起连接的套接口socket上传来的信息,转到缓冲区buffer中,此buffer最大长度为length,并使用flags标志控制此操作。

ssize_t send (int socket, const void *buffer, size_t length, int flags);


send调用把缓冲区buffer长度为length的发送到已经建立起连接的套接口socket。

recv和send也可以用read和write这两个调用替换,这时相当于flags为0的情况。


int shutdown(int socket, int how);


shutdown调用用于关闭指定的套接口描述符,how包括了SHUT_RD, SHUT_WR, SHUT_RDWR。如果使用close代替shutdown,则相当于how为SHUT_RDWR。
事实上存在多个链接使用了一个套接口的情况,所以shutdown和close都只是把指定套接口描述符的引用数减1,减到0才完全撤消此描述符。
shutdown的how参数可以指定关闭的方向,应该比双向关闭的close更值得使用。

4、客户机编程的典型流程:

初始化sockaddr结构(清零)——>调用socket建立套接口——>调用connect建立连接——>建立一个recv/send循环,并设置循环结束条件——>shutdown。

5、服务器编程的典型流程:

初始化sockaddr结构(赋值)——>调用socket建立套接口——>调用listen监听请求和定义阻塞队列——>进入一个无限的while循环——>调用accept接收请求,并生成一个处理这个请求的套接口——>建立一个recv/send循环,并设置循环结束条件——>shutdown。
阅读(1418) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~