Linux系统下实现基于TCP/IP协议的简单Socket通信

  • 网络套接字Socket
    • Socket概念
    • 主机字节序和网络字节序
    • Sockaddr地址结构
  • Socket实现客户端、服务端通信
    • 服务端程序流程
    • 服务端程序
    • 客户端程序流程
    • 客户端程序
    • 运行结果

网络套接字Socket

Socket概念

  Socket(套接宇),用来描述IP地址和端口,是通信链的句柄,应用程序可以通过Socket向网络发送请求或者应答网络请求!Socket是支持TCP/IP协议的网络通信的基本操作单元,是对网络通信过程中端点的抽象表示,包含了进行网络通信所必须的五种信息:连接所使用的协议;本地主机的IP地址:本地远程的协议端口;远地主机的IP地址以及远地进程的协议端口。与管道类似的,Linux系统将其封装成文件的目的是为了统一接口,使得读写套接字和读写文件的操作一致。区别是管道主要应用于本地进程间通信,而套接字多应用于网络进程间数据的传递。
  注意:在网络通信中,套接字一定是成对出现的。换言之,也就是不在通信时,套接字没有成对这个限制。
  网络套接字(Socket)原理可由下图表示:

主机字节序和网络字节序

  提到套接字,不得不理解的就是主机字节序和网络字节序,那么什么是主机字节序和网络字节序呢。我们把字节序分为大端字节序(big endian)和小端字节序(little endian),大端字节序指的是一个整数的高位字节存储在内存的低位地址处,低位字节存储在高位地址处;小端字节序指的是一个整数的高位字节存储在内存的高位地址处,低位字节存储在低位地址处(即大端:高存低,低存高;小端反之)。PC端大多采用的是小端字节序,也被称为主机字节序。
  对于两台使用不同字节序的主机间进行通信时会出现错误。解决这类问题的方法就是发送端总是把要发送的数据转化成大端字节序数据后再发送,而接收端知道对方传送过来的数据总是采用大端字节序,所以接收端可以根据自身采用的字节序决定是否对接收到的数据进行转换(小端机转换,大端机不转换)。因此大端字节序也称为网络字节序,它给所有接收数据的主机提供了一个正确解释收到的格式化数据的保证。

Sockaddr地址结构

  TCP/IP协议族有sockaddr_in和sockaddr_in6两个专用socket地址结构体,它们分别用于IPv4和IPv6:
  Sockaddr地址结构示意图如下:

  Sockaddr地址结构表示:

x struct sockadar_in
{    sa_familyt sin family;/*地址族:AF_INET*/    u int16t sin port;/*端口号,要用网络字节序表示*/    struct in addr sin_addr;/*IPv4地址结构体,见下面*/
};
struct in addr
{    uint32ts addr;/*IPv4地址,要用网络字节序表示*/struct sockaddr_in6
{    sa family_t sin6family;/*地址族:AF_INET6*/    uint16_t sin6port;/*端口号,要用网络字节序表示*/    u int32t sin6 flowinfo;/*流信息,应设置为0*/    struct in6 addr sin6 addr;/*IPv6地址结构体,见下面*/    uint32_t sin6_scope_id;/*scope ID,尚处于实验阶段*/
};
struct in6 addr
{    unsigned char sa_addr[16];/*IPv6地址,要用网络字节序表示*/
};

Socket实现客户端、服务端通信

  实现简单的C/S模型可以根据以下流程完成:

服务端程序流程

服务端:(被动连接,需创建自己的地址信息)

  1. 利用socket函数创建套接字,该函数返回即为用于建立服务端与客户端连接的文件描述符;(称之为句柄)
  2. 创建服务端地址结构,指定服务端的IP协议簇、IP地址和端口号;(服务端创建自己的地址信息)
  3. 调用bind函数绑定IP地址和端口;
  4. 调用listen函数设置监听上限;(同时接受监听的上线数)
  5. 调用accept函数阻塞监听客户端连接;
  6. 调用read函数读socket获取的客户端数据信息,并且完成大小写转换,调用write函数向客户端写入数据信息。(这里read,write函数都是使用与服务器进行通信的文件描述符,并不是用于连接的文件描述符)

服务端程序

#include<iostream>
#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
#include<errno.h>
#include<string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <ctype.h>
#include <arpa/inet.h>
using namespace std;//定义一个端口号(服务端)
#define SERVER_PORT  9527
//#define BUFSIZ _IO_BUFSIZvoid sys_err(const char *str)
{perror(str);exit(1);
}
int main (int argc,char *argv[])
{int link_fd=0;//用于建立连接的文件描述符int c_fd=0;//用于与服务器进行通信int ret;char buf[BUFSIZ];//4096char client_IP[BUFSIZ];//创建套接字link_fd=socket(AF_INET,SOCK_STREAM,0);//检查返回值,判断是否创建成功if(link_fd==-1){sys_err("socket error");}//创建服务端、客户端结构体  初始化成员struct sockaddr_in server_addr,client_addr;//引入头文件#include<netinet/in.h>socklen_t client_addrlen;server_addr.sin_family=AF_INET;server_addr.sin_port=htons(SERVER_PORT);server_addr.sin_addr.s_addr=htonl(INADDR_ANY);//调用bind函数绑定IP地址和端口ret=bind(link_fd,(struct sockaddr*)&server_addr,sizeof(server_addr));//判断是否绑定成功if(ret==-1){sys_err("bind error");}//设置同时与服务器建立连接的上限listen(link_fd,128);//阻塞等待客户端连接client_addrlen=sizeof(client_addr);c_fd=accept(link_fd,(struct sockaddr*)&client_addr,&client_addrlen);//判断是否阻塞等待成功if(c_fd==-1){sys_err("accept error");}//打印客户端IP和端口号cout<<"client ip:"<<inet_ntop(AF_INET,&(client_addr.sin_addr.s_addr),client_IP,sizeof(client_IP))<<endl;cout<<"client port:"<<ntohs(client_addr.sin_port)<<endl;while(1){//读取客户端数据ret=read(c_fd,buf,sizeof(buf));//向屏幕写出write(STDOUT_FILENO,buf,ret);//转换大小写for(int i=0;i<ret;i++){buf[i]=toupper(buf[i]);}//写回到buf中write(c_fd,buf,ret);}close(link_fd);//关闭套接字close(c_fd);return 0;
}

客户端程序流程

客户端:(主动连接,需创建目的地的地址信息)

  1. socket函数创建套接字,创建用于通信的文件描述符;
  2. connect函数与服务端建立连接;(客户端无需绑定,系统会自动分配地址信息)
  3. 调用read函数读取服务端发来的数据信息,write函数向服务端写入数据信息。(这里同样使用的是用于通信的文件描述符)

客户端程序

#include<iostream>
#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
#include<errno.h>
#include<string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <ctype.h>
#include <arpa/inet.h>
using namespace std;//定义一个端口号(服务端)
#define SERVER_PORT  9527
//#define BUFSIZ _IO_BUFSIZvoid sys_err(const char *str)
{perror(str);exit(1);
}
int main (int argc,char *argv[])
{int ret=0; int c_fd=0;//创建用于通信的文件描述符char buf[BUFSIZ];struct sockaddr_in server_addr;//创建服务端地址结构体//初始化成员server_addr.sin_family=AF_INET;server_addr.sin_port=htons(SERVER_PORT);//server_addr.sin_addr.s_addr=htonl(INADDR_ANY);//任意有效ip//将点分十进制的ip地址转化为用于网络传输的二进制数值格式inet_pton(AF_INET,"127.0.0.1",&(server_addr.sin_addr));c_fd=socket(AF_INET,SOCK_STREAM,0);//创建套接字if(c_fd==-1){sys_err("socket error");}//客户端与服务端建立连接ret=connect(c_fd,(struct sockaddr*)&server_addr,sizeof(server_addr));if(ret==-1){sys_err("connect error");}//循环写入数据int counter=5;while(--counter){//客户端写4次hypoticwrite(c_fd,"hypotic\n",8);ret=read(c_fd,buf,sizeof(buf));write(STDOUT_FILENO,buf,ret);sleep(1);}//关闭套接字close(c_fd);return 0;
}

运行结果

服务端:
客户端:

参考:

  1. https://www.runoob.com/w3cnote/android-tutorial-socket1.html
  2. https://blog.csdn.net/qq_28114615/article/details/88421575
  3. linux高性能服务器编程

Linux系统下实现基于TCP/IP协议的简单Socket通信相关推荐

  1. java实例练习——基于TCP/IP协议的多客户端通信

    先说一下大概的思路: 应用多线程来实现服务器与多客户端之间的通信 1.服务器端创建ServerSocket,循环调用accept()等待客户端连接: 2.客户端创建一个Socket并请求与服务器端连接 ...

  2. 基于TCP/IP协议的网络摄像头的QT项目

    目录 项目简述: 1.服务器 步骤一:首先搭建一个基本的服务器框架. 1.初始化服务器的函数主体 2.等待连接 步骤二:数据库的使用,本次项目使用的Sqlite3数据库 1.数据库初始化 2.登录时使 ...

  3. 【网络编程】基于TCP/IP协议的C/S模型

    相关视频--C3程序猿-windows网络编程:第一部分tcp/ip 我的小站--半生瓜のblog 基于TCP/IP协议的C/S模型 基于TCP/IP协议的C/S模型 TCP/IP协议 Client/ ...

  4. 上位机服务器通讯协议,基于TCP/IP协议实现上位机对UR机器人的远程控制

    1.引言 2010年,德国学术界和产业界提出"工业4.0"的概念,即是以智能制造为主导的第四次工业革命,或革命性的生产方法.该战略旨在通过充分利用信息通讯技术和网络空间虚拟系统-信 ...

  5. 打印服务器协议,基于TCP/IP协议的嵌入式网络打印服务器设计

    摘要: 随着电子技术和计算机网络技术的发展,嵌入式系统在家庭和工业的各个领域都得到了广泛的应用,各种信息家电,网络设备以及工业控制领域都出现了嵌入式系统的身影,其数量已经远远超过了各种通用计算机.但是 ...

  6. 基于TCP/IP协议 区别 GET和POST

    基于TCP/IP协议讲解GET和POST的区别(转载于博客园) 在我大万维网世界中,TCP就像汽车,我们用TCP来运输数据,它很可靠,从来不会发生丢件少件的现象.但是如果路上跑的全是看起来一模一样的汽 ...

  7. 基于TCP/IP协议的物联网安卓应用开发基础教程(Android Studio开发)

    [华为云IOT物联网论坛外部版主:中华小能能] 第0章 简介 大家好,在上上上期发布的教程中,教大家如何利用Android Studio开发出一款接入华为云物联网平台并调用相关API完成设备属性查询. ...

  8. 基于TCP/IP协议的Java服务端与Android客户端的Socket通信及数据交互

    基于TCP/IP协议的Java服务端与Android客户端的Socket通信及数据交互 一.前言 1.Java服务端程序代码的项目名为TcpSocketServerOfJava,包名为com.exam ...

  9. TCP/IP 协议标准简单描述

    TCP/IP 协议标准简单描述 说明 分为三部分:中文名称.缩写.说明. 应用层 DNS 域名服务 (DNS) 功能: 将域名转化为IP地址 BOOTP 引导程序协议 (BOOTP) 功能: 允许无盘 ...

最新文章

  1. 2018-3-6论文-网络评论中非结构化信息的应用于研究------(语义矩离)
  2. SAP MM 史上最偷懒的盘点事务代码MI10
  3. npm安装过程出现的问题及解决方式
  4. 架构师之路 — 分布式系统 — CAP 定理
  5. asm 查看 数据文件 修改 时间_更高效的GMX分段模拟方法:修改tpr文件
  6. HashMap 为什么会导致 CPU 100%?文章看不懂?来看这个视频吧!——面试突击 006 期...
  7. java compare时间_java.time.LocalDateTime compareTo()方法
  8. Tensorlayer深度强化学习之Tensorlayer安装
  9. 离线安装CDH5集群及相关软件
  10. 51汇编——矩阵键盘
  11. 网络直播延迟该如何解决这个问题
  12. java 正则拼音,用于匹配拼音的正则表达式
  13. 已解决ValueError: Of the four parameters: start, end, periods, and freq, exactly three must be specifie
  14. [USACO09DEC]视频游戏的麻烦Video Game Troubles(DP)
  15. 国科大学习资料--人工智能原理与算法-第十三次作业解析(学长整理)
  16. 关于sql中like操作符的使用及效率优化问题整理
  17. 309.Best Time to Buy and Sell Stock with Cooldown
  18. 在windows上通过vnc实现远程虚拟界面控制jenson tx2
  19. 安装ps时显示建议重启计算机,安装 photoshop cs6提示建议重新启动计算机的解决办法...
  20. 光波导的入射耦合和出射耦合区域

热门文章

  1. 总结Linux系统压缩和解压文件指令——gzip/gunzip 指令、zip/unzip 指令、tar 指令
  2. 【Linux】循序渐进学运维-实验环境搭建
  3. 算法设计之DP练习(组硬币问题)
  4. 血条HpBar跟随敌人
  5. 抖音MCN与工会的区别
  6. 从青腾爬向宇宙:科技巨头与少年科学家的故事
  7. 如何用matlab进行脑电信号处理,基于matlab的脑电信号处理
  8. 【linux】循序渐进学运维-find
  9. 云服务器怎样杀毒软件,云服务器用什么杀毒软件
  10. [转]C++中const、volatile、mutable的用法