基于TCP协议的Socket通信

发布于:2023-01-04 ⋅ 阅读:(327) ⋅ 点赞:(0)

 

目录

前言:

OSI模型:

TCP/IP模型:

模型对应关系图:

各层的功能及协议: 

1.网络接口物理层:

2.网络层:

3.传输层:

4.应用层:

套接字(Socket):

1,流式套接字(SOCK_STREAM):

2.数据报套接字(SOCK_DGRAM):

3.原始套接字(SOCK_RAM):

Linux实现基于TCP协议的socket通信:

头文件:

客户端:

服务器端:


前言:

这里呢说到了TCP协议就不得不提一下网络体系结构,所谓网络体系结构就是网络的分层结构和各层使用协议的集合。

OSI模型:

其中OSI模型是理想化的,它分为7层:应用层,表示层,会话层,传输层,网络层,数据链路层,物理层;它划分的非常详细但是呢过于复杂,在实际中没有被广泛使用。

TCP/IP模型:

相反TCP/IP模型就相对使用就很广泛了,它分为4层:应用层,传输层,网络层,网络接口物理层;其实这里的应用层是把OSI模型的应用层,表示层,会话层归纳在一起,而网络接口物理层是把OSI模型去的数据链路层和物理层归纳在一起;从而利于实现和高效通信;

模型对应关系图:

各层的功能及协议: 

1.网络接口物理层:

是TCP/IP的最底层,负责将二进制流转换为数据帧,并进行数据帧的发送和接收。数据帧是网络传输的基本单元。协议主要有ARP,RARP,PPP。

2.网络层:

负责在主机之间的通信中选择数据包的传输路径,即路由。还负责处理传入的数据包,检验其有效性,使用路由算法来决定对数据包进行本地处理和转发。所以有时称网络层的功能就是路由和转发;协议主要有:IP,ICMP,IGMP;

3.传输层:

负责实现应用程序之间的通信服务。协议主要有TCP,UDP,STCP。其中TCP和UDP是很重要的,TCP是面向有连接的高可靠的传输控制协议,UDP是面向无连接的不可靠的用户数据报协议。

4.应用层:

负责把封装好的数据交给传输层或者从传输层接收并处理数据。协议主要有:http,tftp。

套接字(Socket):

是一种特殊的I/O接口,也是一种文件描述符。Socket是常用的一种进程之间的通信机制,不仅能实现本地不同进程之间的通信,而且通过网络能在不同主机的进程之间进行通信;而套接字又分三种类型:

1,流式套接字(SOCK_STREAM):

流式套接字提供了可靠的,面向连接的通信流,保证数据传输的可靠性和按序收发。TCP通信就是使用的流式套接字。

2.数据报套接字(SOCK_DGRAM):

数据报套接字实现了一种不可靠的,无连接的服务。数据通过相互独立的报文进行传输,是无序的,并且不保证可靠的传输。UDP通信使用的就是数据报套接字。

3.原始套接字(SOCK_RAM):

原始套接字允许对底层协议进行直接访问,它功能强大但使用不方便,主要用于协议的开发。

Linux实现基于TCP协议的socket通信:

 

头文件:

#ifndef __NET_H
#define __NET_H
#include<string.h>
#include<arpa/inet.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<unistd.h>
#include<netinet/in.h>
#include<netinet/ip.h>

#endif

客户端:

#include<stdio.h>
#include"net.h"
#include<stdlib.h>
//请求连接服务器
int tcp_cliconnect(char*ip,int port)
{
    int tcp_socket=socket(AF_INET,SOCK_STREAM,0);
    if(tcp_socket<0)
    {
        perror("tcp_socket error");
        return -1;
    }   
    printf("socket success\n");
    struct sockaddr_in client;
    client.sin_family=AF_INET;
    client.sin_addr.s_addr=inet_addr(ip);
    client.sin_port=htons(port);
    if(connect(tcp_socket,(struct sockaddr *)&client,sizeof(client))<0)
    {   
        perror("connect faild");
        return -1; 
    }   
    printf("connect success\n");
    return tcp_socket;
}
//通过main函数传参,在执行时数入对应的IP地址和端口号
int main(int argc,char *argv[])
{
    if(argc<3)
    {   
        perror("argc error");
        return -1; 
    }   
    int tcp_socket=tcp_cliconnect(argv[1],atoi(argv[2]));
    if(tcp_socket<0)
    {
        return -1;
    }
    char buf[20]={0};
    printf("write:");
    fgets(buf,sizeof(buf),stdin);
    send(tcp_socket,buf,strlen(buf),0);
    close(tcp_socket);
    return 0;
}
      

服务器端:

#include<stdio.h>
#include"net.h"
#include<stdlib.h>
//监听
int tcp_serconnect(char*ip,int port)
{
    int tcp_socket=socket(AF_INET,SOCK_STREAM,0);
    if(tcp_socket<0)
    {   
        perror("tcp_socket error");
        return -1; 
    }   
    printf("socket success\n");
    struct sockaddr_in server;
    server.sin_family=AF_INET;
    server.sin_addr.s_addr=inet_addr(ip);
    server.sin_port=htons(port);
    if(bind(tcp_socket,(struct sockaddr *)&server,sizeof(server))<0)
    {   
        perror("bind error");
        return -1; 
    }   
    printf("bind success\n");
    if(listen(tcp_socket,5)<0)
    {   
        perror("listen error");
        return -1; 
    }   
    printf("listen success\n");
    return tcp_socket;
}
int main(int argc,char *argv[])
{
    if(argc<3)
    {
        printf("argc error");
        return -1;
    }
    int tcp_socket=tcp_serconnect(argv[1],atoi(argv[2]));
    struct sockaddr_in client;
    int len=sizeof(client);
    //接受客户端的连接请求
    int newtcp_socket=accept(tcp_socket,(struct sockaddr *)&client,&len);
    if(newtcp_socket<0)
    {
        perror("accept faild");
        return -1;
    }
    printf("accept success\n");
    //打印对应的客户端的IP地址和端口号
    printf("client ip=%s port=%d\n",inet_ntoa(client.sin_addr),ntohs(client.sin_port));
    char buf[20]={0};
    recv(newtcp_socket,buf,sizeof(buf),0);
    printf("%s",buf);
    close(newtcp_socket);
    close(tcp_socket);
    return 0;
}


网站公告

今日签到

点亮在社区的每一天
去签到