Chinaunix首页 | 论坛 | 博客
  • 博客访问: 868309
  • 博文数量: 190
  • 博客积分: 7021
  • 博客等级: 少将
  • 技术积分: 1752
  • 用 户 组: 普通用户
  • 注册时间: 2010-05-17 19:26
文章分类

全部博文(190)

文章存档

2014年(9)

2011年(32)

2010年(149)

我的朋友

分类: LINUX

2010-09-19 21:01:39

套接口是位于应用层与TCP/IP协议族通讯的中间软件抽象层,他逻辑上位于传输层与应用层之间。实际上由一组网络编程API组成。套接口的英文名称是Socket,也称为插口或者套接字。Socket数据传输是一种特殊的I/O。

分类

  常用的TCP/IP协议的3种套接字类型如下所示。
  流套接字(SOCK_STREAM):
  流套接字用于提供面向连接、可靠的数据传输服务。该服务将保证数据能够实现无差错、无重复发送,并按顺序接收。流套接字之所以能够实现可靠的数据服务,原因在于其使用了传输控制协议,即TCP(The Transmission Control Protocol)协议。
  数据报套接字(SOCK_DGRAM):数据报套接字提供了一种无连接的服务。该服务并不能保证数据传输的可靠性,数据有可能在传输过程中丢失或出现数据重复,且无法保证顺序地接收到数据。数据报套接字使用UDP(User Datagram Protocol)协议进行数据的传输。由于数据包套接字不能保证数据传输的可靠性,对于有可能出现的数据丢失情况,需要在程序中做相应的处理。
  原始套接字(SOCK_RAW):原始套接字与标准套接字(标准套接字指的是前面介绍的流套接字和数据报套接字)的区别在于:原始套接字可以读写内核没有处理的IP数据包,而流套接字只能读取TCP协议的数据,数据报套接字只能读取UDP协议的数据。因此,如果要访问其他协议发送数据必须使用原始套接字。

简介

  套接字,简单的说就是通信的两方的一种约定,用套接字中的相关函数来完成通信过程

连接方式

  应用层通过传输层进行数据通信时,TCP和UDP会遇到同时为多个应用程序进程提供并发服务的问题。

主要的参数

  区分不同应用程序进程间的网络通讯和连接,主要有3个参数:通信的目的IP地址、使用的传输层协议(TCP或UDP)和使用的端口号。Socket原意是 “插座”。通过将这3个参数结合起来,与一个“插座”Socket绑定,应用层就可以和传输层通过套接字接口,区分来自不同应用程序进程或网络连接的通信,实现数据传输的并发服务。
  Socket可以看成在两个程序进行通讯连接中的一个端点,是连接应用程序和网络驱动程序的桥梁,Socket在应用程序中创建,通过绑定与网络驱动建立关系。此后,应用程序送给Socket的数据,由Socket交网络驱动程序向网络上发送出去。计算机从网络上收到与该Socket绑定IP地址和端口号相关的数据后,由网络驱动程序交给Socket,应用程序便可从该Socket中提取接收到得数据,网络应用程序就是这样通过Socket进行数据的发送与接收的。

字节序
       小端字节序值低字节数据存放在内存低地址处,高字节数据存放在内存高地址处;大端字节序是高字节数据存放在低地址处,低字节数据存放在高地址处
套接字编程:
套接字地址结构:
#include  
struct sockaddr_in
{
     unsigned short   sin_family;          //地址类型
     unsigned short int   sin_port;        //端口号
     struct in_addr    sin_addr;            //IP地址
     unsigned char    sin_zero[8];        //填充字节,一般赋值为0.
};
sin_family表示地址类型,对于使用TCP/IP协议进行的网络编程,该值只能是AF_INET。
数组sin_zero为填充字段,一般赋值为0
一下是设置地址信息的代码:
struct sockaddr_in sock;
sock.sin_family = AF_INET;
sock.si_port = htons(80);        //设置端口号为80,端口为16位的整数
sock.sin_addr.s_addr = inet_addt("202.205.3.195");   //设置地址
menset(sock.sin_zero, 0, sizeof(sock.sin_zero));   //将数组sin_zero清0

创建套接字:
#include
#include
int socket(int domain, int type, int protocol);
参数domain用于指定创建套接字所使用的协议族,常用的协议族有:
1,AF_UNIX:创建只在本机内进行通信的套接字
2,AF_INET:使用IPv4 TCP/IP协议
3,AF_INET6:使用IPv6 TCP/IP协议
参数type指定套接字的类型
1,SOCK_STREAM:创建TCP流套接字
2,SOCK_DGRAM:创建UDP数据报套接字
3,SOCK_RAM:创建原始套接字
参数prorocol一般设定为0
下面的代码创建了一个TCP套接字:
int sock_fd;
sock_fd = socket (AF_INET, SOCK_STREAM, 0);
if (sock_fd < 0)
{
     perror("socket!\n");
     exit(1);
}

建立连接:
函数connect用来在一个指定的套接字上创建一个连接:
#include
#include
int connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen);
参数sockfd是一个由函数socket创建的套接字,如果套接字的类型是SOCK_STREAM,则connect函数用于向服务器发出连接请求,服务器的IP地址和端口号由参数serv_addr指定。如果套接字的类型是SOCK_DGRAM,则connect函数并不建立连接,他只是告诉内核与该套接字进行通信的目的地址,只有该目的的地址发来的数据才会被该socket接受。

绑定套接字:
函数bind用来将一个套接字和某个端口绑定在一起。
#include
#include
int bind(int socket, struct sockaddr * my_addr, socklen_t addrlen);
socket函数只是创建了一个套接字,这个套接字将工作在那个端口上,程序并没有指定,前面提到,只有在客户机/服务器模型中,服务器端得IP地址和端口号一般是固定的,因此在服务器端得程序中,使用bind函数将一个套接字和某个端口绑定在一起

在套接字上监听:
函数listen把套接字转化成被动监听
#include
int listen (int s ,int backlog);
由函数socket创建的套接字是主动套接字,这种套接字可以用来主动请求连接到某个服务器(通过connect函数),但是作为服务器端得程序,通常在某个端口上监听等待来自客户的端的链接请求。
在服务器端通常是用socket创建一个主动套接字,然后调用函数bind将该套接字绑定到某个端口,接着再调用函数listen将该套接字转化为监听套接字,等待一个来自客户端的请求

接受连接:
函数accept用来接受一个连接请求
#include
#include
in accept (int s, struct sockadd * addr, socklen_t * addrlen );
参数  s  是有函数socket创建,经函数bind绑定到本地某一端口上,然后通过函数listen转化而来的监听套接字。
参数addr用来保存发起连接请求的主机的地址和端口
参数addrlen是addr所指向的结构体大小

流式套接字的数据传输:

发送数据:
函数send用来在TCP套接字上发送数据:
#include
#include
ssize_t send ( int s, const void * msg, size_t len, int flags);
函数send只能对处于连接状态的套接字使用,参数s为已建立好连接的套接字描述符,即accept的返回值。
参数msg指向存放待发送数据的缓冲区
参数len为待发数据的长度
参数flag为控制选项
#define BUFFERSIZI    1500
char  send_buf[BUFFERSIZI]

if (send (conn_fd, send_buf , len ,0) < 0)
{
    perror("send");
    exit(1);
}

接受数据:
函数recv用来在TCP套接字上接受数据:
#include
#include
ssize_t recv(int s, void *buf, size_t len ,int flags);
函数recv从参数s所指定的套接字描述符上接收数据并保存到参数buf所指定的缓冲区,参数len则为缓冲区长度

数据报套接字的数据传输:
发送数据:sendto
接受数据:recvfrom

数据的发送和接受:
        sendmsf 函数和recvmsg函数不仅可以用于流式套接口中收发数据,还可以用于数据报套接口中发送和接受数据

关闭套接字:
int  close(int s );
int shutdown (int s ,int how);
用来关闭一个套接字描述符,与关闭文件描述符是类似的

阅读(6118) | 评论(0) | 转发(0) |
0

上一篇:TCP报头结构

下一篇:shell

给主人留下些什么吧!~~