用Socket编程之TCP/IP通信,你会了吗?

Posted 工控云学堂

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用Socket编程之TCP/IP通信,你会了吗?相关的知识,希望对你有一定的参考价值。


OSI参考模型

        OSI(Open System Interconnect),即开放式系统互联。一般都叫OSI参考模型,是ISO(国际标准化组织)组织在1985年研究的网络互连模型。

        ISO为了更好的使网络应用更为普及,推出了OSI参考模型。其含义就是推荐所有公司使用这个规范来控制网络。这样所有公司都有相同的规范,就能互联了。

       OSI定义了网络互连的七层框架(物理层、数据链路层、网络层、传输层、会话层、表示层、应用层),即ISO开放互连系统参考模型。如下图。

        每一层实现各自的功能和协议,并完成与相邻层的接口通信。OSI的服务定义详细说明了各层所提供的服务。某一层的服务就是该层及其下各层的一种能力,它通过接口提供给更高一层。各层所提供的服务与这些服务是怎么实现的无关。

用Socket编程之TCP/IP通信,你会了吗?

TCP/IP协议


理解socket

套接字(socket)

    在网络中用来描述计算机中不同程序与其他计算机程序的通信方式。socket其实是一种特殊的IO接口,也是一种文件描述符。

套接字分为三类:

    流式socket(SOCK_STREAM):流式套接字提供可靠、面向连接的通信流;它使用TCP协议,从而保证了数据传输的正确性和顺序性。

    数据报socket(SOCK_DGRAM):数据报套接字定义了一种无连接的服务,数据通过相互独立的保温进行传输,是无序的,并且不保证是可靠、无差错的。它使用的数据报协议是UDP。

    原始socket:原始套接字允许对底层协议如IP或ICMP进行直接访问,它功能强大但使用复杂,主要用于一些协议的开发。

套接字的数据结构:C语言进行套接字编程时,常会使用到sockaddr数据类型和sockaddr_in数据类型,用于保存套接字信息。

用Socket编程之TCP/IP通信,你会了吗?

TCP服务器的工作过程如下:

服务器创建一个专门的“文件描述符”来监听来自客户端的“三次握手”,然后建立链接
链接建立成功后,服务器会分配一个专门的“通信文件描述符”,用于实现与该客户端的通信
以上通信模型是由于TCP本身的特点:面向连接的,可靠的,字节流通信方式


通信过程

服务器:

创建套接字,返回套接字的文件描述符skfd = socket()

将套接字文件描述符、ip、端口号绑定在一起,建立固定的对应关系bind()

将套接字文件描述符转为被动描述符,用于被动监听客户端链接listen()

与客户端三次握手成功,返回一个通信描述符 fd=accept()

服务器向客户端发送、接收数据 write(fd);send(fd),read(fd);recv(fd);

四次挥手断开连接,可以由任意方发起close(fd);shutdown(fd)



客户端:

创建套接字文件skfd = socket()

主动向服务器发起链接请求,三次握手OK后即链接成功 connet(skfs..)

客户端向服务器发送数据 write(skfd);send(skfd)

客户端接收服务器数据 read(skfd);recv(skfd)

四次挥手断开链接,可以由任意方发起close(fd);shutdown(fd)


#include <sys/stat.h>#include <fcntl.h>#include <errno.h>#include <netdb.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <stdio.h>#include <string.h>#include <stdlib.h>#include <unistd.h> #define SERVER_PORT 6666 /*连接到服务器后,会不停循环,等待输入,输入quit后,断开与服务器的连接*/ int main() {     //客户端只需要一个套接字文件描述符,用于和服务器通信    int clientSocket;     //描述服务器的socket    struct sockaddr_in serverAddr;    char sendbuf[200];    char recvbuf[200];    int iDataNum;     if ((clientSocket = socket(AF_INET, SOCK_STREAM, 0)) < 0) {        perror("socket");        return 1;     }     serverAddr.sin_family = AF_INET;    serverAddr.sin_port = htons(SERVER_PORT);     //指定服务器端的ip,本地测试:127.0.0.1    //inet_addr()函数,将点分十进制IP转换成网络字节序IP    serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");    if (connect(clientSocket, (struct sockaddr *) &serverAddr, sizeof(serverAddr)) < 0) {         perror("connect");         return 1;     }     printf("连接到主机...");    while (true) {        printf("发送消息:");        scanf("%s", sendbuf);        printf("");        send(clientSocket, sendbuf, strlen(sendbuf), 0);        if (strcmp(sendbuf, "quit") == 0)            break;         printf("读取消息:");        recvbuf[0] = \'\';        iDataNum = recv(clientSocket, recvbuf, 200, 0);        recvbuf[iDataNum] = \'\';        printf("%s", recvbuf);     }     close(clientSocket);    return 0; }


以上流程中可以看到服务器在与客户端通信过程中的收发数据使用的是新的文件描述符fd,而客户端收发数据使用的是创建socket时的描述符skfd,这里服务器是需要支持多客户端链接;即每个客户端与服务器进行链接后服务器都会创建一个新的文件描述符fd,用于单独和该客户端进行通信。

End



扫描下方二维码

助你成为优秀的电气工程师

左老师:18073180632(同微信)



以上是关于用Socket编程之TCP/IP通信,你会了吗?的主要内容,如果未能解决你的问题,请参考以下文章

socket编程TCPUDP通信你会了吗?

经典的算法之插入排序,你会了吗

Netty你会了吗?

TCP/IP之socket编程

深入浅出讲解:php的socket通信

TCP/IP网络编程之socket交互流程