文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>linux socket编程基础2

linux socket编程基础2

时间:2010-09-02  来源:xuequansongmo

一、基本套接字函数

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;分别表示正常与错误。

可以编写两个读写函数包含错误处理,以方便使用,如

view sourceprint?
01 <pre class="brush:cpp">#include<errno.h>
02 #include<unistd.h>
03 int 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 }
22 int 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 </pre>
43 三、其他函数<br>getsockname和getpeername
view sourceprint?
1 分别返回套接字的本地地址和对应的远程地址。
view sourceprint?
1 1.域名查找函数
view sourceprint?
1 gethostbyname,gethostbyaddr,uname,gethostname
view sourceprint?
1 struct hostent* gethostbyname(const char*hostname);
view sourceprint?
1 查询指定的域名地址所对应的IP地址,成功返回一个hostent指针结构,否则返回NULL。
view sourceprint?
1 struct hostent{
2 char *h_name;//主机正式名称
3 char **h_aliases;//别名列表
4 int h_addrtype;//地址类型,AF_INET for ipv4
5 int h_length;//地址长度,32bit for ipv4
6 char **h_addr_list;//主机的ip地址列表
7 };
8 #define h_addr h_addr_list[0];

2.查询指定的IP地址对应的域名 
#include<netdb.h>
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返回本机器的域名地址

view sourceprint?
1 一般用uname获取本机的名称,作为gethostname的参数获取本机ip。
view sourceprint?
1 如uname(&myname);//struct utsname myname;
view sourceprint?
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);

}

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

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

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

 

相关阅读 更多 +
排行榜 更多 +
辰域智控app

辰域智控app

系统工具 下载
网医联盟app

网医联盟app

运动健身 下载
汇丰汇选App

汇丰汇选App

金融理财 下载