一、基本套接字函数
socket,connect,bind,listen,accept,close
函数socket创建的套接字是主动套接字,可以用来进行主动连接(调用connect),但是不能接收连接请求,
而服务器的套接字必须能够接受客户机的请求,函数listen的作用就是将一个尚未连接的主动套接字转换成一
个被动套接字(称之为倾听套接字):告诉TCP协议,可以接受连接请求。
倾听套接字是专门用来接收客户机连接请求,完成3次握手操作而用的,TCP不能使用它来标识TCP连接,这样就
需要创建一个新的套接字来标识这个要接收的连接,并将他的描述符返回给应用程序,此即accept的作用。
说明:一个服务器进程通常只需要创建一个倾听套接字,在服务器进程的整个活动期间,用它来接收所有客户机的
连接请求,在服务器进程终止前close这个倾听套接字,而对于每个accept的连接,TCP都创建一个新的连接套接字
来标识这个连接,当服务器处理完这个客户机的请求时,就可以close这个套接字。
二、读写数据函数
read,write,send,receive,sendto,recvfrom(以后介绍)
与读写文件操作类似
read操作时:3种返回结果:>0,=0,<0;分别对应正常返回,读到文件结束符和读错误。
write操作时,2种返回结果:>0,<0;分别表示正常与错误。
可以编写两个读写函数包含错误处理,以方便使用,如
01 | class = "brush:cpp" >#include< errno .h>
|
03 | int read_all( int fd, void *buf, int n) |
11 | nbytes=read(fd,ptr,nleft); |
13 | if ( errno ==EINTR)nbytes=0; |
16 | else if (nbytes==0) break ; |
22 | int write_all( int fd, void *buf, int n) |
30 | nbytes=write(fd,ptr,nleft); |
32 | if ( errno ==EINTR)nbytes=0; |
43 | 三、其他函数 getsockname和getpeername |
1 | gethostbyname,gethostbyaddr,uname,gethostname |
1 | struct hostent* gethostbyname( const char *hostname); |
1 | 查询指定的域名地址所对应的IP地址,成功返回一个hostent指针结构,否则返回NULL。 |
8 | #define h_addr h_addr_list[0]; |
2.查询指定的IP地址对应的域名
#include
struct hostent *gethostbyaddr(const char *addr,size_t len,int family)
参数addr实际上是一个指向in_addr结构类型的指针,包含要查询的ip地址,len指示其长度family=AF_INET。返回的结果位于hostent结构的h_name域。
【在网络程序中为了便于使用,应能处理ip地址和域名地址两种地址形式,对于一个给定的地址,一般先假设是个ip地址,用inet_aton处理,如果失败,在进行域名查找。比如下面的通用地址处理函数】
int addr_generic(char*address,struct in_addr *inaddr){
struct hostent *he;
if(inet_aton(address,inaddr)==1)return 1;
he=gethostbyname(address);
if(he!=NULL){
*inaddr=*(struct in_addr*)he->he_addr->list[0];
return 1; }
else return 0;
}
3.uname与gethostname返回本机器的域名地址
1 | 一般用uname获取本机的名称,作为gethostname的参数获取本机ip。 |
1 | he=gethostname(myname.nodename) |
4.服务有关的函数
getservbyname,getservbyport
struct servent*getservbyname(const char*servname,const char*protostrname);//查找服务的端口号
struct servent *getservbyport(int port,const char *protoname)//查找端口的服务
端口均是网络字节顺序的。
struct servent{
char *s_name;
char **s_aliases;
int s_port;
char *s_proto;
};
四、网络数据格式
文本字符串,二进制数据无需进行特殊的处理,整数的发送和接收需要进行一些处理。
16位,32位可以借助htons&ntohs和htonl&ntohl转换,64位的则需要借助函数vsprintf和sscanf
比如:void sender(int sockfd,long data)
{ char buf[10];
sprintf(buf,"%ld",data);
write(sockfd,buf,strlen(buf));
}
void receiver(int sockfd,long *data)
{
char buf[10];
read(sockfd,buf,sizeof(buf));
sscanf(buf,"ld",data);
}
指针数据的传输:只能传输指针所指的具体内容;
结构体数据的传输:发送方依次传送结构体中各成员变量,而接收方使用相同的顺序接收个成员变量。
浮点数据的传输:可以字符串形式发送和接收。
阅读(1283) | 评论(0) | 转发(0) |