Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1172305
  • 博文数量: 272
  • 博客积分: 6445
  • 博客等级: 准将
  • 技术积分: 2833
  • 用 户 组: 普通用户
  • 注册时间: 2006-03-04 23:22
文章分类

全部博文(272)

文章存档

2024年(1)

2023年(5)

2022年(3)

2021年(18)

2020年(9)

2019年(1)

2018年(13)

2017年(11)

2015年(9)

2013年(2)

2012年(4)

2011年(24)

2010年(114)

2009年(6)

2008年(29)

2007年(13)

2006年(10)

我的朋友

分类: C/C++

2010-09-02 10:30:20

一、基本套接字函数

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>
02#include
03int read_all(int fd,void*buf,int n)
04{
05  int nleft;
06  int nbytes;
07  char *ptr;
08  ptr=buf;
09  nleft=n;
10  for(;nleft>0;){
11    nbytes=read(fd,ptr,nleft);
12    if(nbytes<0){
13      if(errno==EINTR)nbytes=0;
14      else return -1;
15    }
16    else if(nbytes==0)break;
17    nleft-=nbytes;
18    ptr+=nbytes;
19  }
20  return n-nleft;
21}
22int write_all(int fd,void*buf,int n)
23{
24  int nleft;
25  int nbytes;
26  char *ptr;
27  ptr=buf;
28  nleft=n;
29  for(;nleft>0;){
30    nbytes=write(fd,ptr,nleft);
31    if(nbytes<=0){
32      if(errno==EINTR)nbytes=0;
33      else return -1;
34    }
35    
36    nleft-=nbytes;
37    ptr+=nbytes;
38  }
39  return n;
40}
41 
42
43三、其他函数
getsockname和getpeername
1分别返回套接字的本地地址和对应的远程地址。
11.域名查找函数
1gethostbyname,gethostbyaddr,uname,gethostname
1struct hostent* gethostbyname(const char*hostname);
1查询指定的域名地址所对应的IP地址,成功返回一个hostent指针结构,否则返回NULL。
1struct hostent{
2char *h_name;//主机正式名称
3char **h_aliases;//别名列表
4int h_addrtype;//地址类型,AF_INET for ipv4
5int h_length;//地址长度,32bit for ipv4
6char **h_addr_list;//主机的ip地址列表
7};
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如uname(&myname);//struct utsname myname;
1he=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);

}

指针数据的传输:只能传输指针所指的具体内容;

结构体数据的传输:发送方依次传送结构体中各成员变量,而接收方使用相同的顺序接收个成员变量。

浮点数据的传输:可以字符串形式发送和接收。

 

阅读(1242) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~