Linux下使用TCP协议完成一个简单的client-service通信

1 篇文章 0 订阅

最近学习了网络编程,简单分享一下自己学习的内容

TCP协议简介

TCP向应用层提供了一个可靠的,有序的,面向连接的,基于字节流的全双工的通信协议。

它能提供高可靠性通信,即数据无误,数据无丢失,数据无失序,数据无重复。

三次握手协议

TCP是面向连接的。通过三次握手协议实现。

第一步:客户端向服务器端发送一个SYN=1,seq=x的TCP报文,并进入SYN_SEND状态,等待服务器确认。

第二步:服务器端收到客户端的报文后,返回一个SYN=1,ACK=1,seq=y,ack=x+1的报文,标识客户端的SYN被确认,此时服务器进入SYN_RECV状态。

第三步:客户端收到服务器的报文后,向服务器发送一个ACK=1,seq=x+1,ack=y+1的报文确认,客户端和服务器进入ESTAB_LISHED状态,完成TCP连接。

 TCP CS搭建流程图

 

 函数实现

客户端:实现了向服务器发送数据,创建了一个子线程来接受服务器转发的数据

  

 1 #include <stdio.h> 
  2 #include <string.h> 
  3 #include <unistd.h> 
  4 #include <sys/types.h> 
  5 #include <sys/socket.h> 
  6 #include <arpa/inet.h> 
  7 #include <pthread.h> 
  8  
  9 int mysckfd; 
 10 void *recv_func(void *p) 
 11 { 
 12     char buf1[100]; 
 13     while(1) 
 14     { 
 15         memset(buf1,0,sizeof(buf1)); 
 16         int res = recv(mysckfd,buf1,sizeof(buf1),0); 
 17         if(res < 0) 
 18         { 
 19             puts("recv_func error"); 
 20             break; 
 21         } 
 22         puts(buf1); 
 23     } 
 24 } 
 25 int main() 
 26 { 
 27     //socket 创建一个通信套接字
 28     mysckfd = socket(AF_INET, SOCK_STREAM, 0); 
 29     if(mysckfd < 0) 
 30     { 
 31         puts("socket error."); 
 32         return -1; 
 33     } 
 34     puts("socket success."); 
 35     //connect 连接服务器端
 36     int ret = -1; 
 37     struct sockaddr_in myser; 
 38     myser.sin_family = AF_INET; 
 39     myser.sin_port = htons(7777); 
 40     myser.sin_addr.s_addr = inet_addr("192.168.9.132"); 
 41  
 42     ret = connect(mysckfd, (struct sockaddr *)&myser, sizeof(myser)); 
 43     if(ret != 0) 
 44     { 
 45         puts("connect server error.");
 46         close(mysckfd);
 47         return -1;
 48     }
 49     puts("connect server success.");
 50     //send发送函数
 51     char buf[50];                                                                                                                                                                
 52     pthread_t thread;
 53     while(1)
 54     {
 55         memset(buf,0,sizeof(buf));
 56         gets(buf);
 57         send(mysckfd, buf, sizeof(buf), 0);

 58        //创建一个线程进行接收
 59         void *recv_func(void *);
 60         pthread_create(&thread,NULL,recv_func,0);
 61     }
 62     
 63    //close
 64     close(mysckfd);
 65     return 0;
 66 }

服务器端:使用多进程实现了服务器端同时处理多个客户端请求,并将收到的数据转发给源客户端
 
 

 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/types.h>
 #include <sys/socket.h>

 #include <arpa/inet.h>
 #include <unistd.h>


//接受发送子函数

 int recv_send_func(int connfd)
  {

   while(1)
    {
        char buf[100];
        memset(buf, 0, sizeof(buf));
        int ret = recv(connfd, buf, sizeof(buf), 0);
        if(ret > 0)
        {
            puts(buf);
            send(connfd,buf,sizeof(buf),0);
        }
        else if(ret == 0)
        {
            break;
        }
    }
}

//初始化子函数
int Init_func(unsigned short port)
{

    //socket创建一个监听套接字
    int myserfd = socket(AF_INET, SOCK_STREAM, 0);
    if(myserfd < 0)
    {
        puts("socket error!");
        return -1;
    }
    puts("socket success!");
    //bind给服务器绑定端口号和IP,注意:端口号不能和已使用的端口号重复
    int ret = -1;
    struct sockaddr_in myser;
    memset(&myser, 0, sizeof(myser));
    myser.sin_family = AF_INET;
    myser.sin_port = htons(port);
    myser.sin_addr.s_addr = htonl(INADDR_ANY);

    ret = bind(myserfd, (struct sockaddr *)&myser, sizeof(myser));
    if(ret != 0)
    {
        puts("bind error!");
        close(myserfd);
        return -1;
    }
    puts("bind success!");
    //listen监听客户端的连接请求
    ret = listen(myserfd, 5);
    if(ret != 0)
    {
        puts("listen error!");
        close(myserfd);
        return -1;
    }
    puts("listen success!");
    return myserfd;
}

//主函数

int main()
{
    int serfd = Init_func(7777);  
    int connfd = -1;    
    struct sockaddr_in mycli;
    int len = sizeof(mycli);
    while(1)
    {
        connfd = accept(serfd,(struct sockaddr *)&mycli,&len);
        if(connfd > 0)
        {
            pid_t pid = fork();
            if(pid == 0)
            {
                while(1)
                {
                    recv_send_func(connfd);
                }
                close(connfd);
                exit(0);
            }
        }
    }
    return 0;
}

总结:

搭建TCP CS模型并不是很困难,学习掌握了TCP的各个函数并理解其搭建流程加以利用就能成功完成。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值