第15章 套接字
2016-04-22 22:31
232 查看
创建套接字:
#include <sys/types.h>
#include <sys/socket.h>
int socket( int domain, int types, int protocol);
domain:
AF_UNIX, AF_LOCAL // address family 地址是文件名
AF_INET //IPV4
AF_INET6 //IPV6
types:
1. stream: SOCK_STREAM //流
2. datagram: SOCK_DGRAM //数据报
socket返回的描述符,用read和write调用
close系统调用结束socket连接
不同的domain 有不同的地址格式:
AF_UNIX : 定义在sys/un.h 中
struck sockaddr_un {
sa_family_t sun_family;
char sun_path[ ];
};
AF_INET : 定义在netinet/in.h中
struct sockaddr_in {
short int sin_family;
unsigned short int sin_port;
struct in_addr sin_addr;
}; 其中:
sruct in_addr {
unsigned long int s_addr;
};
命名: 要使用创建好的套接字,需要命名. //服务器端
#include <sys/socket.h>
int bind( int socket, const struct sockaddr *address, size_t address_len); //succes return 0.
作用是把socket定义的name space 指向 address所在的地址. 如:
server_address.sun_family = AF_UNIX;
strcpy(server_address.sun_path, "filename");
server_len = sizeof(server_address);
bind(server_sockfd, (struct sockaddr *)&server_address, server _len);
建立套接字队列: 保存未处理的请求
#include <sys/socket.h>
int listen( int socket, int backlog); //backlog位保存的最大个数 成功 返0
接收连接:
服务器程序建立并命名了套接字后 可通过accept系统调用来等待客户建立对该套接字的连接
#include <sys/socket.h>
int accept( int socket, strucct sockaddr *sddress, size_t *address_len);
客户端请求连接:
#inclued <sys/socket.h>
int connect ( int socket, const struct socket sockaddr *address, size_t address_len);
关闭套接字:
调用close来终止服务器和客户上的套接字连接.
服务器: 一般在read调用返回0是关闭.
网络套接字:
系统使用1024以内的端口. 端口可在文件: /etc/services 中查到.
/etc/hosts 本地主机地址 及 共享网络地址
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
inet_addr函数把网络地址转换位binary 地址
例:
int server_sockfd, client_sockfd;
int server_len, client_len;
struct sockaddr_in server_address;
struct sockaddr_in client_address;
server_sockfd = socket(AF_INET,SOCK_STREAM,0);
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = inet_addr("127.0.0.1");
server_address.sin_port = 9734;
server_len = sizeof(server_address);
bind(server_sockfd,(struct sockaddr *)&server_address,server_l en);
listen(server_sockfd, 5);
接收来自计算机网络的任何网络接口连接: INADDR_ANY 32位整数 用在 sin_addr.s_addr 中,
不同的cpu存储的字节顺序不同,intel 是 4-3-2-1 高到低 ibm的是 低到高的顺序,这样导致ip地址不一样,解决方法是通过在netinet/in.h中函数完成:
#include <netinet/in.h>htonl //host to net long 缩写
htons,ntohl,ntohs 函数 //我的centos 是 include <arpa/inet.h>中
服务器:
server_address.sin_addr.s_addr = htonl(INADDR_ANY);
server_address.sin_port = htons(9734);
客户端:
address.sin_addr.s_addr = inet_addr("127.0.0.1"); //不变
address.sin_port = htons(9374);
网络信息: 主机数据库函数
#include <netdb.h>
struct hostent *gethostbyaddr(const void *addr, size_t len, int type);
struct hostent *gethostbyname(const char *name);
其中:
struct hostent {
char *h_name;
char **h_aliases;
int h_addrtype;
int h_length;
char **h_addr_list
};
服务信息函数:
#include <netdb.h>
struct servent *getservbyname(const char *name,const char *proto);
struct servent * getservbyport( int port,const char *proto);
如: servinfo = getservbyname(“daytime”, “tcp”);
printf(“daytime port is %d\n”, ntohs(servinfo -> s_port));
其中:
proto包含tcp和udp两个参数--->SOCK_STREAM, SOCK_DGRAM
struct servent {
char *s_name;
char **s_aliases;
int s_port;
char *s_proto;
};
要获得某计算机主机数据库信息,可用gethostbyname,但要注意返回地址列表转换位正确的
地址类型,并用函数inet_ntoa将其从网络字节序转换位可打印的字符串.
#include <arpa/inet.h>
char *inet_ntoa(struct in_addr in) // inet_addr(*(struct in_addr *)*a->h_addr_list);
其作用是将因特网主机地址转换为一个点分四元组格式的字符串.
另:
#include <unistd.h>
int gethostname(char *name, int namelength)
作用是将当前主机的名字写入name指向的字符串.
internet 守护进程(deamon) xinetd/inetd)
/etc/xinetd.conf and files in
/etc/xinetd.d directory
多客户:
在server程序中,使用fork(),
例:
socket(), bind(),listen() 后, if(fork == 0) //子进程, 进行操作: read(fd,buffer,) write(fd,buffer, ) close(fd)
else //父进程 : close(fd);
select系统调用:
select函数多数据结构fd_set进行操作,,它是由打开的文件描述符构成的集合. 有一组定义好的宏可以用来控制这些集合:
#include <sys/types.h>
#incldue <sys/time.h>
void FD_ZERO(fd_set *fd); // 初始化fd_set为空集合
void FD_CLR( int fd,fd_set *fdset); //
void FD_SET(int fd, fd_set *fdset);
int FD_ISSET(int fd, fd_set *fdset); // 如果 fd 是 fdset所指向的结构中的元素,则返回非0值
fd_set中文件描述符最大数由常量FD_SETSIZE指定.
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout);
select调用测试文件描述符集合中,是否有一个文件描述符已处于可读状态或可写状态或错误
状态,它将阻塞以等待某个文件描述符进入上述这些状态.
返回值为准备好的文件描述符的个数,未发生变化的文件描述符在fd_set 中清零. 用FD_ISSET查找改动的fd.
ioctl(fd,FIONREAD,&int_val);读取缓存中的字节数并将其储存到整型变量int_val中
使用selectd多客户:
数据报:datagrams
当客户需要发送一个短小的查询请求给server,并希望接收一个短小的相应时,使用UDP提供的服务. UDP 在局域网中非常可靠.
方法:
套接字和close系统调用. 但用sendto和recvfrom代替read和write调用.
开启daytime服务的方法:
vi /etc/xinet.d/daytime-udp 将disable的yes改为no,然后重启 systemctl restart xinetd.service
#include <sys/types.h>
#include <sys/socket.h>
int socket( int domain, int types, int protocol);
domain:
AF_UNIX, AF_LOCAL // address family 地址是文件名
AF_INET //IPV4
AF_INET6 //IPV6
types:
1. stream: SOCK_STREAM //流
2. datagram: SOCK_DGRAM //数据报
socket返回的描述符,用read和write调用
close系统调用结束socket连接
不同的domain 有不同的地址格式:
AF_UNIX : 定义在sys/un.h 中
struck sockaddr_un {
sa_family_t sun_family;
char sun_path[ ];
};
AF_INET : 定义在netinet/in.h中
struct sockaddr_in {
short int sin_family;
unsigned short int sin_port;
struct in_addr sin_addr;
}; 其中:
sruct in_addr {
unsigned long int s_addr;
};
命名: 要使用创建好的套接字,需要命名. //服务器端
#include <sys/socket.h>
int bind( int socket, const struct sockaddr *address, size_t address_len); //succes return 0.
作用是把socket定义的name space 指向 address所在的地址. 如:
server_address.sun_family = AF_UNIX;
strcpy(server_address.sun_path, "filename");
server_len = sizeof(server_address);
bind(server_sockfd, (struct sockaddr *)&server_address, server _len);
建立套接字队列: 保存未处理的请求
#include <sys/socket.h>
int listen( int socket, int backlog); //backlog位保存的最大个数 成功 返0
接收连接:
服务器程序建立并命名了套接字后 可通过accept系统调用来等待客户建立对该套接字的连接
#include <sys/socket.h>
int accept( int socket, strucct sockaddr *sddress, size_t *address_len);
客户端请求连接:
#inclued <sys/socket.h>
int connect ( int socket, const struct socket sockaddr *address, size_t address_len);
关闭套接字:
调用close来终止服务器和客户上的套接字连接.
服务器: 一般在read调用返回0是关闭.
网络套接字:
系统使用1024以内的端口. 端口可在文件: /etc/services 中查到.
/etc/hosts 本地主机地址 及 共享网络地址
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
inet_addr函数把网络地址转换位binary 地址
例:
int server_sockfd, client_sockfd;
int server_len, client_len;
struct sockaddr_in server_address;
struct sockaddr_in client_address;
server_sockfd = socket(AF_INET,SOCK_STREAM,0);
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = inet_addr("127.0.0.1");
server_address.sin_port = 9734;
server_len = sizeof(server_address);
bind(server_sockfd,(struct sockaddr *)&server_address,server_l en);
listen(server_sockfd, 5);
接收来自计算机网络的任何网络接口连接: INADDR_ANY 32位整数 用在 sin_addr.s_addr 中,
不同的cpu存储的字节顺序不同,intel 是 4-3-2-1 高到低 ibm的是 低到高的顺序,这样导致ip地址不一样,解决方法是通过在netinet/in.h中函数完成:
#include <netinet/in.h>htonl //host to net long 缩写
htons,ntohl,ntohs 函数 //我的centos 是 include <arpa/inet.h>中
服务器:
server_address.sin_addr.s_addr = htonl(INADDR_ANY);
server_address.sin_port = htons(9734);
客户端:
address.sin_addr.s_addr = inet_addr("127.0.0.1"); //不变
address.sin_port = htons(9374);
网络信息: 主机数据库函数
#include <netdb.h>
struct hostent *gethostbyaddr(const void *addr, size_t len, int type);
struct hostent *gethostbyname(const char *name);
其中:
struct hostent {
char *h_name;
char **h_aliases;
int h_addrtype;
int h_length;
char **h_addr_list
};
服务信息函数:
#include <netdb.h>
struct servent *getservbyname(const char *name,const char *proto);
struct servent * getservbyport( int port,const char *proto);
如: servinfo = getservbyname(“daytime”, “tcp”);
printf(“daytime port is %d\n”, ntohs(servinfo -> s_port));
其中:
proto包含tcp和udp两个参数--->SOCK_STREAM, SOCK_DGRAM
struct servent {
char *s_name;
char **s_aliases;
int s_port;
char *s_proto;
};
要获得某计算机主机数据库信息,可用gethostbyname,但要注意返回地址列表转换位正确的
地址类型,并用函数inet_ntoa将其从网络字节序转换位可打印的字符串.
#include <arpa/inet.h>
char *inet_ntoa(struct in_addr in) // inet_addr(*(struct in_addr *)*a->h_addr_list);
其作用是将因特网主机地址转换为一个点分四元组格式的字符串.
另:
#include <unistd.h>
int gethostname(char *name, int namelength)
作用是将当前主机的名字写入name指向的字符串.
internet 守护进程(deamon) xinetd/inetd)
/etc/xinetd.conf and files in
/etc/xinetd.d directory
多客户:
在server程序中,使用fork(),
例:
socket(), bind(),listen() 后, if(fork == 0) //子进程, 进行操作: read(fd,buffer,) write(fd,buffer, ) close(fd)
else //父进程 : close(fd);
select系统调用:
select函数多数据结构fd_set进行操作,,它是由打开的文件描述符构成的集合. 有一组定义好的宏可以用来控制这些集合:
#include <sys/types.h>
#incldue <sys/time.h>
void FD_ZERO(fd_set *fd); // 初始化fd_set为空集合
void FD_CLR( int fd,fd_set *fdset); //
void FD_SET(int fd, fd_set *fdset);
int FD_ISSET(int fd, fd_set *fdset); // 如果 fd 是 fdset所指向的结构中的元素,则返回非0值
fd_set中文件描述符最大数由常量FD_SETSIZE指定.
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout);
select调用测试文件描述符集合中,是否有一个文件描述符已处于可读状态或可写状态或错误
状态,它将阻塞以等待某个文件描述符进入上述这些状态.
返回值为准备好的文件描述符的个数,未发生变化的文件描述符在fd_set 中清零. 用FD_ISSET查找改动的fd.
ioctl(fd,FIONREAD,&int_val);读取缓存中的字节数并将其储存到整型变量int_val中
使用selectd多客户:
数据报:datagrams
当客户需要发送一个短小的查询请求给server,并希望接收一个短小的相应时,使用UDP提供的服务. UDP 在局域网中非常可靠.
方法:
套接字和close系统调用. 但用sendto和recvfrom代替read和write调用.
开启daytime服务的方法:
vi /etc/xinet.d/daytime-udp 将disable的yes改为no,然后重启 systemctl restart xinetd.service
相关文章推荐
- 结队练习源代码
- 初识hibernate
- 四.Linux系统中文搜索命令
- servlet详解(第二篇)
- 用户场景描述
- Linux每天学习一个命令之which命令
- BestCoder Round #81 (div.2) 1004 String(动态规划)
- app advice:苹果iOS 2.0 – iOS 8.0各版本发布时间表
- 一个移植十分方便的类似printf函数
- 初心
- http://blog.csdn.net/tkwxty/article/details/34474501
- 电脑管家(私人版)
- 用户场景描述
- boost::optional<T>
- LINUX内核学习总结
- GCD 之 dispatch_benchmark 测量指定代码块执行时间
- 关于在使用c3p0 连接池配置数据库连接时出现 com.mchange.v2.resourcepool.CannotAcquireResourceExceptiond问题的解答
- OSX下brew cask install 本地安装pkg,dmg
- stl容器区别(内存布局和使用场合): vector list deque set map
- Android下的Java安装及环境的配置