一 什么是套接字
  套接字是一种通信机制,凭借这种机制,客户/服务器系统的开发既可以在本地单机上进行,也可以跨网络进行。

二 套接字属性
  套接字的特性由3个属性确定,它们是:域,类型和协议
   1 套接字的域
    域指定套接字通信中的网络介质,最常见的套接字域是AF_INET,它指的是Internet网络,其底层的协议——网际(IP)只有一个地址族,它使用一种特定的方式来指定网络中的计算机,即人们常说的IP地址。

    AF_UNIX域是UNIX文件系统域,即使是一台还没联网的计算机上的套接字也可以使用这个域,这个域的底层协议是文件输入/输出,而它的地址就是文件名。
 
  2 套接字类型
    因特网协议提供了两种通信机制:流和数据报。
    2.1 流套接字
       流套接字提供的是一个有序,可靠,双向字节流的连接,因此,发送的数据可以确保不会丢失,复制或乱序到达,并且在这一过程中发生的错误也不会显示出来。大的消息将被分片,传输,再重组。
       流套接字由类型SOCK_STREAM指定,它们是在AF_INET域中通过TCP/IP(TCP代表是传输控制协议,IP代表是网际协议)连接实现的。
    2.2 数据报套接字
     数据报套接字由类型SOCK_DGRAM指定,不建立和维持一个连接。它对可以发送的数据报的长度有限制。数据报作为一个单独的网络消息被传输,它可能会丢失,复制或乱序到达。
     数据报套接字是在AF_INET域中通过UDP/IP连接实现的,它提供的是一种无序的不可靠服务(UDP代表的是用户数据报协议)。
     数据报适用于信息服务中的“单次”查询,它主要用来提供日常状态信息或执行低优先级的日志记录。基于数据报的服务器通常不保留连接信息。
 
 三 套接字的连接过程


  1 创建套接字

#include <sys/types.h>
#include <sys/socket.h>
int socket(int domain,      //指定协议族
       int type,       //指定这个套接字的通信类型
       int protocol     //指定使用的协议,将该参数设置为0表示默认协议
      );

  以下是协议族:   AF_UNIX:UNIX域协议(文件系统本地套接字)
            AF_INET:ARPA因特网协议(UNIX网络套接字)
         AF_ISO:ISO标准协议
         AF_NS:施乐网络系统协议
         AF_IPX:Novell IPX协议
         AF_APPLETALK:Appletalk DDS
  socket系统调用返回一个描述符,当这个套接字连接到另一端的套接字后,我们就可以用read和write系统调用,通过这个描述符来在套接字上发送和接收数据了。    
 
  2 套接字地址
   每个套接字域都有其自己的地址格式,对于AF_UNIX域套接字来说,它的地址有结构sockaddr_un来描述,该结构定义在头文件sys/un.h中

#include <sys/un.h>
struct sockaddr_un{
sa_family_t sun_family;//AF_UNIX
char sun_path[];//pathname,长度限制为108个字符
};

  对于AF_INET域,套接字地址由结构sockaddr_in来指定,该结构定义在头文件netinet/in.h中, 一个AF_INET套接字由它的域,端口号和IP地址来完全确定。

#include <netinet/in.h>
struct sockaddr_in{
short int sin_family;         //AF_INET;
unsigned short int sin_port;    //端口号
struct in_addr sin_addr;      //IP地址
};

  IP地址结构in_addr被定义为:

struct in_addr{
unsigned long int s_addr;    //使用inet_addr(const char *cp)函数将一个点分十进制的IP转换成一个长整数型数
};

  3 命名套接字
   通过给套接字命名,可以让创建的套接字被其他进程使用

#include <sys/socket.h>
int bind(int socket,                //创建的socket
      const struct sockaddr *address,    //套接字地址地址,在AF_INET域中则是struct sockaddr_in类型,在AF_UNIX域中则是struct sockaddr_un类型
      size_t address_len                //地址结构的长度
     );                      //bind调用在成功时返回0,失败时返回-1并设置errno

  bind系统调用把参数address中的地址分配给与文件描述符socket关联的为命名套接字,地址结构的长度由参数address_len传递。


  errno的值              描述


  EBADF              文件描述符无效
  ENOTSOCK             文件描述符对应的不是一个套接字
  EINVAL                文件描述符对应的是一个已命名的套接字
  EADDRNOTAVAIL         地址不可用
  EADDRINUSE            地址已经绑定了一个套接字

  EACCESS             权限不足
  ENOTDIR,ENAMETOOLONG   表明选择的文件不符合要求


  4 创建套接字队列
  创建套接字队列能够保存服务器未处理的请求

#include <sys/socket.h>
int listen(int socket,     //socket文件标识符
       int backlog    //用来设置队列中可以容纳的未处理连接的最大数目,超过这个数目,往后的连接将被拒绝,导致客户的连接请求失败。
      );          //listen函数在成功时返回0,失败时返回-1

  5 客户请求连接
  客户程序通过在一个未命名套接字和服务器监听套接字之间建立连接的方法

#include <sys/socket.h>
int connect(int socket,                //指定的套接字将连接到参数address指定的服务器套接字
       const struct sockaddr* address,    //这个和服务器端的bind操作部分一样,看步骤2,3
       size_t address_len            //指定address指向的结构的长度
       );                     //成功时,connect调用返回0,失败时返回-1并设置errno

    errno值              描述


    EBADF            传递给socket参数的文件描述符无效
    EALREADY          该套接字上已经有一个正在进行中的连接
    ETIMEOUT          连接超时
    ECONNREFUSED       连接请求被服务器拒绝


  如果连接不能立刻建立,connect调用将阻塞一段超时时间,一旦这个超时时间到达,连接将被放弃,connect调用失败。但如果connect调用被一个信号中断,而该信号又得到了处理,connect调用还是会失败
  connect的阻塞特性可以通过设置该文件描述符的O_NONBLOCK标志来改变。

int flags=fcntl(socket,F_GETFL,);
fcntl(socket,O_NONBLOCK|flags);

  6 服务器接受连接

#include <sys/socket.h>
int accept(int socket,              //客户程序连接到由socket参数指定的套接字上
       struct sockaddr *address,     //客户的地址,如果我们不关心客户的地址,可以将address参数指定为空指针
       size_t *address_len        //客户地址的长度,如果客户地址的长度超过这个值,它将被截断。
      );

  accept系统调用只有当有客户程序试图连接到由socket参数指定的套接字上时才返回,这里的客户是指套接字队列中排在第一个的未处理的连接。
  一般情况下,如果套接字队列中没有未处理的连接,accept将阻塞(程序将暂停)直到有客户建立连接为止,和请求连接一样,可以通过使用fcntl函数对套接字文件描述符设置O_NONBLOCK标志
  当有未处理的客户连接时,accept函数将返回一个新的套接字文件描述符。

  7 关闭连接
  close系统用来结束套接字连接。

四 示例

服务器程序server.c

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h> int main(){
int server_sockfd,client_sockfd;
int server_len,client_len;
struct sockaddr_in server_address;
struct sockaddr_in client_address;
//为服务器创建一个未命名的套接字
server_sockfd=socket(AF_INET,SOCK_STREAM,);
//命名套接字
server_address.sin_family=AF_INET;
server_address.sin_addr.s_addr=inet_addr("127.0.0.1");
server_address.sin_port=;
server_len=sizeof(server_address);
bind(server_sockfd,(struct sockaddr *)&server_address,server_len);
//创建一个连接队列,开始等待客户进行连接
listen(server_sockfd,);
while(){
char ch;
printf("server waiting\n");
//接受一个连接
client_len=sizeof(client_address);
client_sockfd=accept(server_sockfd,(struct sockaddr*)&client_address,&client_len);
//对client_sockfd套接字上的客户进行读写操作
read(client_sockfd,&ch,);
ch++;
write(client_sockfd,&ch,);
close(client_sockfd);
}
}

客户程序client.c

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h> int main(){
int sockfd;
int len;
struct sockaddr_in address;
int result;
char ch='A';
//为客户创建一个套接字
sockfd=socket(AF_INET,SOCK_STREAM,);
//命名套接字,与服务器保持一致
address.sin_family=AF_INET;
address.sin_addr.s_addr=inet_addr("127.0.0.1");
address.sin_port=;
len=sizeof(address);
//将我们的套接字连接到服务器的套接字
result=connect(sockfd,(struct sockaddr*)&address,len);
if(result==-){
perror("oops:client1");
exit();
}
//现在就可以通过sockfd进行读写操作了
write(sockfd,&ch,);
read(sockfd,&ch,);
printf("char from server=%c\n",ch);
close(sockfd);
exit();
}

  

Linux学习笔记30——套接字的更多相关文章

  1. linux学习笔记之套接字

    一.基础知识. 1:套接字基础. 1,是通信端点的抽象. 2,在UNIX类系统中被当作是一种文件描述符. 3,套接字通信域. 域 描述 AF_INET IPV4因特网域 AF_INET6 IPV6因特 ...

  2. 网络协议学习笔记(五)套接字Socket

    概述 前面学习网络知识的时候写过一篇关于套接字的随笔见<JAVA SOCKET 详解>,现在本人正在系统的学习网络知识,现在除了温故知新之外,在详细的学习记录一下套接字的知识. Socke ...

  3. Linux 学习笔记

    Linux学习笔记 请切换web视图查看,表格比较大,方法:视图>>web板式视图 博客园不能粘贴图片吗 http://wenku.baidu.com/view/bda1c3067fd53 ...

  4. deepin linux学习笔记

    目录 deepin linux学习笔记 前言 linux常用命令 ls 显示文件夹内容 cd 切换当前目录 pwd 查看当前工作目录 mkdir 新建文件夹 rm 删除文件或文件夹 mv 移动文件 c ...

  5. (转)Linux最常用指令及快捷键 Linux学习笔记

    Linux最常用指令及快捷键 Linux学习笔记 原文:http://blog.csdn.net/yanghongche/article/details/50827478 [摘自 鸟叔的私房菜]--转 ...

  6. linux学习笔记2-linux的常用命令

    第一篇博客:linux学习笔记1-ubuntu的安装与基本设置 之中,已经介绍了如何安装linux操作系统,以及一些基本的设置修改. 本篇博客主要介绍linux中的一些常用的终端命令 ======== ...

  7. deepin linux 学习笔记(二)——文本编辑器

    目录 deepin linux 学习笔记(二)--文本编辑器 前言 nano 小巧的命令行编辑器 通用 编辑 定位 排版 配置 vim 思路独特的超级编辑器 命令模式 插入模式 底线模式(末行模式) ...

  8. linux学习笔记2 - linux常用命令

    转载请标注原链接:http://www.cnblogs.com/xczyd/p/5543731.html 第一篇博客:linux学习笔记1-ubuntu的安装与基本设置 之中,已经介绍了如何安装lin ...

  9. Linux 学习笔记之超详细基础linux命令 Part 1

    Linux学习笔记之超详细基础linux命令 by:授客 QQ:1033553122   说明:主要是在REHL Server 6操作系统下进行的测试 --字符界面虚拟终端与图形界面之间的切 方法:[ ...

随机推荐

  1. 如何写robots.txt?

    robin 发表在 八月 2, 2006 在国内,网站管理者似乎对robots.txt并没有引起多大重视,应一些朋友之请求,今天想通过这篇文章来简单谈一下robots.txt的写作. robots.t ...

  2. 如何在Sql2008中获取表字段属性和注释?

    如何在Sql2008中获取表字段属性和注释? select b.[value] from sys.columns a left join sys.extended_properties b on a. ...

  3. wget 使用技巧

    wget 是一个命令行的下载工具.对于我们这些 Linux 用户来说,几乎每天都在使用它.下面为大家介绍几个有用的 wget 小技巧,可以让你更加高效而灵活的使用 wget. $ wget -r -n ...

  4. CI 笔记7,easyui 异步加载

    在做后台导航时,需要异步加载,pid和id的循环问题,在controller中,建立另外一个方法,嵌套循环,查找是否pid〉1. public function nav_list() { $this- ...

  5. c#yield,IEnumerable,IEnumerator

    foreach 在编译成IL后,实际代码如下: 即:foreach实际上是先调用可枚举对象的GetEnumerator方法,得到一个Enumerator对象,然后对Enumerator进行while循 ...

  6. linux命令行抓取网页快照-(xvfb+CutyCapt)

    目的: 在一台没有安装X-server的Debian服务器上实现命令行抓取网页快照 软件: xvfb(在命令行下实现对X-server的模拟,渲染图形进行缓存)-在没有安装X-Server的环境下提供 ...

  7. 开源字体包缩减font-spider

    最近公司产品用微软雅黑,被告~  领导要求产品后台系统必须更换字体,美工给了个宋体,个人觉得太丑,就网上搜了些处理方法使用 CSS属性 @font-face 自定义字体, 最后决定用 思源黑体 (思源 ...

  8. new、delete用法(一)

    第一部分:new的使用: #define DEBUG_NEW new(THIS_FILE, __LINE__)解释 THIS_FILE:表示当前类所处的文件名: __LINE__:表示分配内存操作所在 ...

  9. 获取动态SQL查询语句返回值(sp_executesql)

    在写存储过程时经常会遇到需要拼接SQL语句的情况,一般情况下仅仅是为了执行拼接后的语句使用exec(@sql)即可. 而今天的一个存储过程却需要获取动态SQL的查询结果. 需求描述:在某表中根据Id值 ...

  10. Windows Phone 之文件下载进度和速度显示

    用http协议来下载网络上的文件,通常我们需要获取文件的下载进度和下载的速度来给用户等待过程的一个交代,那么在windows phone 7下可以使用WebClient类来实现这一功能,HttpWeb ...