套接字类型与协议设置

   我们先了解一下创建套接字的那个函数 int socket(int domain,int type,int protocol);成功时返回文件描述符,失败时返回-1.其中,domain是套接字使用中的协议族(Protocol Family)信息。type套接字类型里面的数据传输类型信息。protocol计算机通信中使用的协议信息。

协议族(Protocol Family)

协议族类型有:

    PE_INET          IPV4

    PE_INET6          IPV6

PF_LOCAL        本地通信的UNIX协议族

      PF_PACKET        底层套接字的协议族

PF_IPX         IPX Novell协议族

套接字类型(Type)

  套接字类型指的是套接字的数据传输方式,通过socket函数的第二个参数传递,只有这样才能决定创建的套接字的数据传输方式。决定了协议族并不能同时决定数据传输方式。也就是说socket函数第一个参数的PF_INET协议族存在多重数据传输方式。

第一种:面向连接的套接字(SOCK_STREAM)

  如果给第二个参数传递SOCK_STREAM,将创建面向连接的套接字。特点:

  • 套接字连接必须一一对性。
  • 可靠的、按序传递的、基于字节的面向连接的数据传输方式的套接字。

收发数据的套接字内部有缓冲(buffer),简言之就是字节数组。通过套接字传输的数据将保存到该数组中。因此,收到数据并不意味着马上调用read函数。只要不超过数组容量,则有可能数据填充满缓冲后通过一次read函数调用全部读完,也有可能分成多次调用read函数调用进行读取。也就是说,在面向连接的套接字中,read和write函数调用多次并无太大意义,所以说面向连接的套接字编程不存在数据边界。

如果套接字缓冲已满是否意味着数据丢失?首先调用read函数从缓冲区读取部分数据,因此,缓冲并不总是满的。但如果read函数读取的速度比接收数据的速度慢,则缓冲有可能被填满,此时套接字无法在接收数据,但即使这样也不会发生数据丢失。因为传输端套接字将停止传输。也就是说,面向连接的套接字会根据接收端的状态传输数据,如果传输出错还会提供重传服务。因此,面向连接的套接字除特殊的情况不会发生数据丢失。

第二种:面向消息的套接字(SOCK_DGRAM)

  如果给第二个参数传递SOCK_DGRAM,将创建面向消息的套接字。特点:

  • 不可靠的、不按序传递的、以数据的告诉传输为目的的套接字。
  • 传输的数据具有数据边界。

套接字协议信息

第三个参数主要用在同一协议族中存在多重传输方式相同的协议,数据传输方式相同,但协议不同。此时靠第三个参数具体指定协议信息。

简单的例子:

  要求在IPV4协议族中创建面向连接的套接字。其中在TCP/IP网络编程系列之一中创建服务端和客户端的代码,服务端的代码不需要改变,只改变客户端的代码,更改read函数的调用方式。

TCPClient代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>

#define MAXSIZE 30
void Error_Handling(char* message);

int main(int argc,char* argv[])
{
    int sock;
    struct  sockaddr_in serverAddr;
    char message[MAXSIZE];
    int str_len=0;
    int idx=0,read_len=0;
    if(argc != 3)
    {
        printf("Usage : %s <IP> <Port> \n",argv[0]);
        exit(1);
    }
    sock = socket(PF_INET,SOCK_STREAM,0);
    if(sock == -1)
    {
        Error_Handling("sock() error");
    }
    memset(&serverAddr,0,sizeof(serverAddr));
    serverAddr.sin_family=AF_INET;
    serverAddr.sin_addr.s_addr=inet_addr(argv[1]);
    serverAddr.sin_port=htons(atoi(argv[2]));
    if(connect(sock,(struct sockaddr*)&serverAddr,sizeof(serverAddr))==-1)
    {
        Error_Handling("connect() error");
    }
   
    while(( read_len = read(sock,&message[idx++],1)))
    {
        if(read_len==-1)
        {
            Error_Handling("read() error\n");
        }
        str_len+=read_len;
    }
    printf("Message from server : %s \n",message);
    printf("Function read call count:%d \n",str_len);
    close(sock);
    return 0;
}

void Error_Handling(char *message)
{
    fputs(message,stderr);
    fputc('\n',stderr);
    exit(1);
}

TCP/IP网络编程系列之二(初级)的更多相关文章

  1. TCP/IP网络编程系列之三(初级)

    TCP/IP网络编程系列之三-地址族与数据序列 分配给套接字的IP地址和端口 IP是Internet Protocol (网络协议)的简写,是为首发网络数据而分配给计算机的值.端口号并非赋予计算机值, ...

  2. TCP/IP网络编程系列之四(初级)

    TCP/IP网络编程系列之四-基于TCP的服务端/客户端 理解TCP和UDP 根据数据传输方式的不同,基于网络协议的套接字一般分为TCP和UDP套接字.因为TCP套接字是面向连接的,因此又称为基于流的 ...

  3. TCP/IP网络编程系列之一(初级)

    概述 网络编程实际上就是编写程序使两台联网的计算机相互的交换数据.操作系统会提供名为“ 套接字 ”的部件.套接字是网络数据传输的软件设备,即使对网络数据传输原理不太熟悉也无关紧要.我们也能通过套接字完 ...

  4. TCP/IP网络编程之多进程服务端(二)

    信号处理 本章接上一章TCP/IP网络编程之多进程服务端(一),在上一章中,我们介绍了进程的创建和销毁,以及如何销毁僵尸进程.前面我们讲过,waitpid是非阻塞等待子进程销毁的函数,但有一个不好的缺 ...

  5. TCP/IP网络编程之多线程服务端的实现(二)

    线程存在的问题和临界区 上一章TCP/IP网络编程之多线程服务端的实现(一)的thread4.c中,我们发现多线程对同一变量进行加减,最后的结果居然不是我们预料之内的.其实,如果多执行几次程序,会发现 ...

  6. TCP/IP网络编程之优于select的epoll(二)

    基于epoll的回声服务端 在TCP/IP网络编程之优于select的epoll(一)这一章中,我们介绍了epoll的相关函数,接下来给出基于epoll的回声服务端示例. echo_epollserv ...

  7. TCP/IP网络编程之基于TCP的服务端/客户端(二)

    回声客户端问题 上一章TCP/IP网络编程之基于TCP的服务端/客户端(一)中,我们解释了回声客户端所存在的问题,那么单单是客户端的问题,服务端没有任何问题?是的,服务端没有问题,现在先让我们回顾下服 ...

  8. 浅谈TCP/IP网络编程中socket的行为

    我认为,想要熟练掌握Linux下的TCP/IP网络编程,至少有三个层面的知识需要熟悉: 1. TCP/IP协议(如连接的建立和终止.重传和确认.滑动窗口和拥塞控制等等) 2. Socket I/O系统 ...

  9. TCP/IP网络编程之进程间通信

    进程间通信基本概念 进程间通信意味着两个不同进程间可以交换数据,为了完成这一点,操作系统中应提供两个进程可以同时访问的内存空间.但我们知道,进程具有完全独立的内存结构,就连通过fork函数创建的子进程 ...

随机推荐

  1. 使用群晖NAS:配置Git server

    1.首先在群晖的DSM的控制面板中创建一个用户例如是Git_test(我给了管理员权限) 2.在套件中心安装 Git server 3.打开Git server 勾选用户 Git_test 4.在控制 ...

  2. RabbitMQ(6) 集群部署

    单节点部署 rabbitmq单节点部署比较简单,可以使用apt-get等工具快速安装部署. wget -O- https://www.rabbitmq.com/rabbitmq-release-sig ...

  3. windows 下git 的配置安装与使用

    一.安装GIT(过于简单略过) 二.配置git 二(一).配置git的user name和email 打开 git bash,输入 $ git config --global user.name &q ...

  4. Django中类视图的简介及使用

    类视图 1 类视图引入 以函数的方式定义的视图称为函数视图,函数视图便于理解.但是遇到一个视图对应的路径提供了多种不同HTTP请求方式的支持时,便需要在一个函数中编写不同的业务逻辑,代码可读性与复用性 ...

  5. 通过powershell实现基础认证钓鱼获得密码

    本文来自https://www.secpulse.com/archives/4131.html $cred = $host.ui.promptforcredential('Failed Authent ...

  6. location.host 与 location.hostname 的区别

    JavaScript 中,大多数情况下,我们不会发现 location.host 与 location.hostname 的区别,因为大多数情况下,我们的网页用的是 80 端口. 他们的区别: loc ...

  7. JQ上传预览+存数据库

    因为之前老师讲的方法有不少BUG 现在经过完善已经修复 之前老是讲的方法是每一张都会被传到后台文件夹里面去 导致在预览过程中如果刷新页面 那么预览的图片不能从后台文件夹中删除  这个方法实现在本地预览 ...

  8. 缺一个UI设计

    这几天弄小程序的界面真的是太艰难了,神呐,请赐我一个UI吧 甚至,在第二种布局下的渐变过渡,都拿笔来计算了TT 还有这个色调的选择,在避免过渡效果突兀的处理上,真的是很费工夫啊: 我谁都不服,就服那些 ...

  9. 深入理解Eureka之源码解析

    转载请标明出处: http://blog.csdn.net/forezp/article/details/73017664 本文出自方志朋的博客 Eureka的一些概念 Register:服务注册 当 ...

  10. Python源码分析(二) - List对象

    python中的高级特性之一就是内置了list,dict等.今天就先围绕列表(List)进行源码分析. Python中的List对象(PyListObject) Python中的的PyListObje ...