免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 814 | 回复: 0
打印 上一主题 下一主题

网络编程socket总结(一) [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-08-15 15:42 |只看该作者 |倒序浏览

                                                               
       
       
       
       
       
       
一、套接子的理解
套接字是一种使用标准UNIX文件描述符(file
descriptor)与其他程序通信的方式,可、套接字可以
看作是处于不同主机之间的两个程序的连接端点,一方面程序将要传输的信息写入套接字,另一方面
则通过读取套接字的数据来获得传输的信息。在使用套接字之前,先来了解下面的数据结构。
二、套接字编程相关的数据结构
1、表示套接口的数据结构
struct socket
套接口是由 socket
数据结构代表的,形式如下:
struct
socket
{
socket_state
state;
  /* 指明套接口的连接状态,一个套接口的连接状态可以有以下几种
                                             
套接口是空闲的,还没有进行相应的端口及地址的绑定;还没有连接;
            
                 正在连接中;已经连接;正在解除连接。
                                             */
unsigned
long          flags;
struct
proto_ops
       ops;            /* 指明可对套接口进行的各种操作
*/
struct
inode           inode;
          /* 指向 sockfs
文件系统中的相应 inode
*/
struct
fasync_struct   *fasync_list;   /* Asynchronous wake up list   */
struct
file            *file;         
/* 指向 sockfs
文件系统*/
struct
sock
            sk;             /* 任何协议族都有其特定的套接口特性,
                                                      
            该域就指向特定协议族的套接口对
象。
                                                   
          */
wait_queue_head_t
     wait;
short
                 type;
unsigned
char          passcred;
};
2、描述套接口通用地址的数据结构
struct sockaddr
在 bind、connect
等系统调用中,特定于协议的套接口地址结构指针都要强制转换成
该通用的套接口地址结构指针。结构形式如下:
struct
sockaddr {
sa_family_t
   sa_family;   /* 用于指定地址族,如果是TCP/IP通信,该值取PF_INET*/
char
          sa_data[14]; /* 用于保存套接字的IP地址和端口信息
*/
};
3、描述因特网地址结构的数据结构
struct sockaddr_in
其数据结构与sockaddr类似定义如下:
struct
sockaddr_in
{
short
int sin_family;/*用于指定地址族*/
unsigned
short int sin_port;/*套接子通信的端口*/
struct
in_addr sin_addr;/*通信的IP地址*/
unsigned
char sin_zero[8];/*用以填充0,保持与struct
sockaddr大小相同*/
};
由于sockaddr和sockaddr_in的数据结构是一样的指向struct
sockaddr_in的指针可以通过强制
转换,转换成指向sockaddr结构的指针。
三、套接口编程的几个重要步骤及相关常用函数介绍:
1、创建套接口,由系统调用
socket 实现:
int
socket(int domain, int type,int protocol);
domain:说明我们网络程序所在的主机采用的通讯协族(AF_UNIX和AF_INET等).
AF_UNIX只能够用
于单一的Unix系统进程间通信,而AF_INET是针对Internet的,因而可以允许在远程
主机之间通信
(当我们
man socket时发现
domain可选项是
PF_*而不是AF_*,因为glibc是posix的实现
所以用PF代替了AF,不过我们都可以使用的).
type:我们网络程序所采用的通讯协议(SOCK_STREAM,SOCK_DGRAM等)
SOCK_STREAM表明我们用
的是TCP协议,这样会提供按顺序的,可靠,双向,面向连接的比特流.
SOCK_DGRAM 表明我们用的是
UDP协议,这样只会提供定长的,不可靠,无连接的通信.
protocol:由于我们指定了type,所以这个地方我们一般只要用0来代替就可以了
socket为网络通讯
做基本的准备.成功时返回文件描述符,失败时返回-1,看errno可知道出错的详细情况
socket系统调用返回一个文件描述符,他在许多方面都类似于底层的文件描述符。当这个套接字连接
到另一断的套接字后,就可以调用read和write系统调用,通过这个文件描述符来在套接字上发送
和接受数据了,close系统调用用于结束套接字连接。
2、绑定地址
根据传输层协议(TCP、UDP)的不同,客户机及服务器的处理方式也有很大不同。但是,不管通信双方
使用何种传输协议,都需要一种标识自己的机制。
通信双方一般由两个方面标识:地址和端口号(通常,一个
IP 地址和一个端口号常常被称为一个套接
口)。根据地址可以寻址到主机,根据端口号则可以寻址到主机提供特定服务的进程,实际上,一个特
定的端口号代表了一个提供特定服务的进程。
int
bind(int sockfd, struct sockaddr *my_addr, int addrlen);
sockfd:是由socket调用返回的文件描述符.
addrlen:是sockaddr结构的长度.
my_addr:是一个指向sockaddr的指针.
在中有 sockaddr的定义
struct
sockaddr {
        unisgned
short as_family;
        char
sa_data[14];
};
不过由于系统的兼容性,我们一般不用这个头文件,而使用另外一个结构(struct
sockaddr_in) 来
代替.在上面有sockaddr_in的定义
struct
sockaddr_in {
        unsigned
short sin_family;
        unsigned
short int sin_port;
        struct
in_addr sin_addr;
        unsigned
char sin_zero[8];
};
我们主要使用Internet所以sin_family一般为AF_INET,sin_addr设置为INADDR_ANY表示可以
和任何的主机通信,sin_port是我们要监听的端口号.sin_zero[8]是用来填充的.
Bind将本地的
端口同socket返回的文件描述符捆绑在一起.成功是返回0,失败的情况和socket一样
3、监听(由服务器端发起)
int
listen(int sockfd,int backlog);
sockfd:是bind后的文件描述符.
backlog:设置请求排队的最大长度.当有多个客户端程序和服务端相连时,
使用这个表示可以介绍的
排队长度.
listen函数将bind的文件描述符变为监听套接字.返回的情况和bind一样.
4、请求建立连接(由
TCP 客户发起)
对于采用面向连接的传输协议
TCP
实现通信来说,一个比较重要的步骤就是通信双方建立连接(如果采
用 udp
传输协议则不需要),由系统调用
connect()完成:
int
connect(int sockfd, struct sockaddr * serv_addr,int addrlen);
sockfd:socket返回的文件描述符.
serv_addr:储存了服务器端的连接信息.其中sin_add是服务端的地址
addrlen:serv_addr的长度
connect函数是客户端用来同服务端连接的.成功时返回0,sockfd是同
服务端通讯的文件描述符
失败时返回-1.
与 connect()相对应,在服务器端,通过系统调用
listen(),指定服务器端的套接口为监听套
接口,监听每一个向服务器套接口发出的连接请求,并通过握手机制建立连接。内核为
listen()维护两
个队列:已完成连接队列和未完成连接队列。
5、接受连接请求(由
TCP 服务器端发起)

务器端通过监听套接口,为所有连接请求建立了两个队列:已完成连接队列和未完成连接队列(每个
监听套接口都对应这样两个队列,当然,一般服务器只有一个监
听套接口)。通过
accept()调用,服
务器将在监听套接口的已连接队列头中,返回用于代表当前连接的套接口描述字。
int
accept(int sockfd, struct sockaddr *addr,int *addrlen);
sockfd:是listen后的文件描述符.
addr,addrlen是用来给客户端的程序填写的,服务器端只要传递指针就可以了.
bind,listen和
accept是服务器端用的函数,accept调用时,服务器端的程序会一直阻塞到有一个
客户程序发出了
连接.
accept成功时返回最后的服务器端的文件描述符,这个时候服务器端可以向该描述符写信息了.
失败时返回-1.
对于采用 TCP
传输协议进行通信的服务器和客户机来说,一定要经过客户请求建立连接,服务器接
受连接请求这一过程;而对采用
UDP 传输协议的通信双方则不需要这一步骤。
6、通信
客户机可以通过套接口接收服务器传过来的数据,也可以通过套接口向服务器发送数据。前面所有的准
备工作(创建套接口、绑定等操作)都是为这一步骤准备的。
常用的从套接口中接收数据的调用有:recv、recvfrom、recvmsg
等,常用的向套接口中发送数据的
调用有 send、sendto、sendmsg
等。
//recv从指定套接字中获取发送的消息
ssize_t
recv(int s//指定接收端套接字描述符
                        ,
void *
buf//指明一个缓冲区,该缓冲区用来存放recv函数接收到的数据
                        ,
size_t
len/指明buf的长度
                        ,
int
flags)
//一般置0
//
recvfrom 用于接收套接字发送来的信息
ssize_t
recvfrom(int s        //套接字文件描述符
                                ,
void *buf     //指向接收到信息的指针
                                ,
size_t
len     //内存空间的最大长度
                                ,
int
flags     //控制参数,用于控制是否接收代外数据
                                ,
struct sockaddr *
from  //指向发送方地址的指针
                                ,
socklen_t *
fromlen)
  //指向发送方地址大小的指针
//send用于将信息发送到指定的套接字文件描述符中
ssize_t
send(int s//指定发送端套接字描述符
                        ,const
void *buf//指明一个存放应用程序要发送数据的缓冲区;
                        ,
size_t
len//指明实际要发送的数据的字节数
                        ,
int
flags)//一般置0
//
sendto用于发送信息给指定的主机,当用于面向通信的的连接时to和tolen将被忽略
ssize_t
sendto(int s            //套接字文件描述符
                        ,
const void *
  buf  //指向要发送信息地址空间的指针
                        ,
size_t
len         //要发送的字节
                        ,
int
flags          // 控制参数,用于控制是否接收数据以及是否预览报文
                  
,const struct sockaddr
*
to
                        ,
socklen_t
  tolen)

7、关闭套接字
close(sockfd);
               
               
               
               
               
               
               
               
               
               
               

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/74012/showart_1131554.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP