利用网络套接字实现TCP交互

我们来了解一下TCP交互流程:
这里写图片描述

大致流程如下:
(1)服务器根据地址的类型(属于ipv4还是ipv6等)、socket类型(比如TCP、UDP)去创建socket,创建出的套接字socket本质上是个文件描述符
(2)服务器绑定IP地址和端口号到套接字socket
(3)服务器socket**监听**端口号请求,随时准备接收客户端发来的连接,但这个时候服务器的socket并没有被打开。
(4)根据地址的类型(属于ipv4还是ipv6等)、socket类型(比如TCP、UDP)去**创建socke**t,创建出的套接字socket本质上也是个文件描述符。
(5)客户端根据服务器的ip地址和端口号,试图连接服务器
(6)服务器socket**接收到客户端的socket请求,被动打开,开始接收客户端的请求并等待客户端返回连接信息。这个阶段,服务器的**accept方法是阻塞的,即等到刚才试图连接的客户端返回连接信息,accept方法才能返回,才能继续接收下一个最新的客户端连接请求。
(7)客户端连接成功,向服务器发送连接状态信息
(8)服务器accept方法返回,连接成功
(9)客户端发送消息
(10)服务端接收消息
(11)客户端关闭
(12)服务端关闭

我们根据这个流程实现TCP交互:
tcpserver.c(服务器)

#include <stdio.h>                        
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <string.h>
#include <errno.h>
#include <netinet/in.h>
#include <arpa/inet.h>

//服务器
int main(int argc, char* argv[])
{
    if(argc!=3){
        printf("Usage %s is port\n",argv[0]);
        return 1;
    }

    //创建套接字
    int sock = socket(AF_INET, SOCK_STREAM, 0);
    if(sock < 0){
        perror("socket");
        return 2;
    }

    struct sockaddr_in local;
    local.sin_family = AF_INET;
    local.sin_port = htons(atoi(argv[2]));
    local.sin_addr.s_addr = inet_addr(argv[1]);

    //绑定
    if(bind(sock, (struct sockaddr*)&local, sizeof(local))<0)
    {
        perror("bind");
        return 3;
    }

    //监听
    if(listen(sock, 5)<0)
    {
        perror("listen");
        return 4;
    }

    while(1)
    {
        char buf[1024];                                                     
        buf[0]='\0';
        struct sockaddr_in peer;
        socklen_t len = sizeof(peer);

        //接受请求
        int new_sock=accept(sock, (struct sockaddr*)&peer,&len);
        if(new_sock<0)
        {
            perror("accept");
            return 5;
        }
        inet_ntop(AF_INET, &peer.sin_addr, buf, sizeof(buf));
        printf("get a connect,ip:%s,port:%d\n",buf, ntohs(peer.sin_port));

        while(1)
        {
            ssize_t s = read(new_sock, buf, sizeof(buf));
            if(s > 0)
            {
                buf[s]='\0';
                printf("[%s:%d] %s",inet_ntoa(peer.sin_addr),\
                        ntohs(peer.sin_port),buf);
            }                                                               
           else
            {
                printf("client quit\n");
                break;
            }
            write(new_sock,buf,strlen(buf)+1);
        }
    }

    close(sock);
    return 0;
}

tcpclient.c(客户端)

#include <stdio.h>                           
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <string.h>
#include <errno.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main(int argc,char *argv[])
{
    if(argc != 3){
        printf("Usage %s ip port\n",argv[0]);
        return 1;
    }

    //创建套接字
    int sock=socket(AF_INET,SOCK_STREAM, 0);
    if(sock < 0)
    {
        perror("socket");
        return 2;
    }

    struct sockaddr_in server;
    server.sin_family = AF_INET;
    server.sin_port = htons(atoi(argv[2]));
    server.sin_addr.s_addr = inet_addr(argv[1]);

    //建立连接
    int ret = connect(sock, (struct sockaddr*)&server, \
            sizeof(server));
    if(ret < 0){
        perror("connect");
        return 3;
    }

    printf("connect success...\n");

    while(1){
        char buf[1024];//缓冲区
        buf[0]='\0';
        printf("Please Enter:");
        fflush(stdout);
        ssize_t s = read(0, buf, sizeof(buf));                              
        }
        write(sock, buf, sizeof(buf));
        if(strncmp(buf, "quit",4)==0)
            break;
        read(sock, buf, sizeof(buf));
        printf("server :%s",buf);
    }

    close(sock);
    return 0;
}         

在本地网络中建立连接,运行结果如下:
这里写图片描述

猜你喜欢

转载自blog.csdn.net/ZWE7616175/article/details/80260420