实现客服端和服务端的全双工通信

IO多路复用机制

  • 使用I/O多路复用技术。其基本思想是:
    • 先构造一张有关描述符的表,然后调用一个函数。
    • 当这些文件描述符中的一个或多个已准备好进行I/O时函数才返回。
    • 函数返回时告诉进程哪个描述符已就绪,可以进行I/O操作。

全双工的通信基于TCP和IO多路复用。 TCP可以使客服端和服务器连接起来进行通信。

思路:

先建立客服端和服务端的通信

服务端:

1.创建套接字(socket)

2.将ip号和端口号绑定到套接字中(bind)

3.监视(将主动套接字转换为被动套接字)(listen)

4.阻塞函数等待客服端连接(accept)

5.进行io多路复用完成通信(select   fd_set)()

客服端:(客服端和服务端的基本操作基本一样)

1.创建套接字(socket)

2.连接服务器()

5.进行io多路复用完成通信(select   fd_set)

直接上代码: 服务器:

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include<stdio.h>
#include<string.h>
#include <netinet/in.h>
#include <netinet/ip.h> 
#include <stdlib.h>
#include <sys/select.h>
#include <sys/time.h>
#include <unistd.h>
#include <arpa/inet.h>


//建立服务器与客服端完成全双工通讯,使用TCP和IO复用
int main(int argc, char const *argv[])
{
    //1.创建套接字
    int sock;
    sock=socket(AF_INET,SOCK_STREAM,0);
    if(sock<0)//容错判断
    {
        perror("sock_stream err\n");
        return -1;
    }
    //2.端口号和IP号绑定
    struct sockaddr_in add;
    add.sin_addr.s_addr=inet_addr(argv[1]);//ip号
    add.sin_family=AF_INET;//ipv4协议
    add.sin_port=htons(atoi(argv[2]));//端口号
    int len=sizeof(add);
    if(bind(sock,(struct sockaddr*)&add,len)<0)
    {
        perror("inet_addr err\n");
        return -1;
    }
    //3.监听
    if(listen(sock,8)<0)
    {
        perror("listen err\n");
        return -1;
    }

    //4.等待连接时会阻塞
    int sockfd;
    sockfd=accept(sock,NULL,NULL);
    if(sockfd<0)
    {
        perror("sockfd err\n");
        return -1;
    }
    //5.使用io多路复用与客服端
    //5.1创建表
    fd_set readig,flag;
    FD_ZERO(&readig);
    FD_SET(0,&readig);
    FD_SET(sockfd,&readig);
    int max=sockfd;
    char buf[64]="";
    while(1)
    {
        flag=readig;
        int revt=select(max+1,&flag,NULL,NULL,NULL);//监听表
        if(revt<0)
        {
            perror("select err\n");
            return -1;
        }
        if(FD_ISSET(0,&flag))
        {
            gets(buf);
            write(sockfd,buf,64);
            memset(buf,0,64);
        }
        if(FD_ISSET(sockfd,&flag))
        {
            int rea=read(sockfd,buf,64);
            if(rea>0)
            {
                printf("%s\n",buf);
            memset(buf,0,64);
            }
            else if(rea==0)
            {
                printf("客服端关闭\n");
                break;
            }else
            {
                perror("错误\n");
                break;
            }
           
        }
    }
    close(sockfd);
    return 0;
}

客服端:

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



//基于TCP,创建全双工客服端 使用标准输入0,标准输出用使用套接字用io多路复用
int main(int argc, char const *argv[])
{
    if(argc!=3)
    {
        printf("输入ip号和端口号:\n");
        return -1;
    }
    //1.创建套接字
    int sock;
    sock=socket(AF_INET,SOCK_STREAM,0);
    if(sock<0)
    {
        perror("sock err\n");
        return -1;
    }
    //2.连接服务器
    struct sockaddr_in add;
    add.sin_addr.s_addr=inet_addr(argv[1]);
    add.sin_family=AF_INET;
    add.sin_port=htons(atoi(argv[2]));
    int len=sizeof(add);
    if(connect(sock,(struct sockaddr*)&add,len)<0)//连接服务器
    {
        perror("inet_addr err\n");
        return -1;
    }
    //3.使用io多路复用来判断输入输出实现全双工
    fd_set readfds,tempfds;
    FD_ZERO(&readfds);
    FD_SET(0,&readfds);
    FD_SET(sock,&readfds);
    int max=sock;
    char buf[64]="";
    while(1)
    {
        tempfds=readfds;
        int ret=select(max+1,&tempfds,NULL,NULL,NULL);
        if(ret<0)
        {
            perror("select err\n");
            return -1;
        }
        if(FD_ISSET(0,&tempfds))
        {
            gets(buf);
            write(sock,buf,64);
             memset(buf,0,64);
        }
        if(FD_ISSET(sock,&tempfds))
        {
           
           read(sock,buf,64);
            printf("%s\n",buf);
             memset(buf,0,64);
        }
    }
    close(sock);
    return 0;
}

运行结果:

欢迎大家在评论区讨论!

下面是一个简单的Java Netty客户端服务端代码案例: 服务端代码: ```java import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; public class Server { private int port; public Server(int port) { this.port = port; } public void run() throws Exception { EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new ServerHandler()); } }) .option(ChannelOption.SO_BACKLOG, 128) .childOption(ChannelOption.SO_KEEPALIVE, true); ChannelFuture f = b.bind(port).sync(); f.channel().closeFuture().sync(); } finally { workerGroup.shutdownGracefully(); bossGroup.shutdownGracefully(); } } public static void main(String[] args) throws Exception { int port = 8080; new Server(port).run(); } } ``` 客户端代码: ```java import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.Socket; public class Client { private String host; private int port; public Client(String host, int port) { this.host = host; this.port = port; } public void run() throws Exception { Socket socket = new Socket(host, port); BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); PrintWriter out = new PrintWriter(socket.getOutputStream(), true); out.println("Hello Server!"); String response = in.readLine(); System.out.println("Server response: " + response); in.close(); out.close(); socket.close(); } public static void main(String[] args) throws Exception { String host = "localhost"; int port = 8080; new Client(host, port).run(); } } ``` 这个简单的示例演示了如何使用Netty创建一个客户端服务端。在服务端中,我们创建了一个`ServerBootstrap`实例并指定了一个`NioEventLoopGroup`作为boss和worker组。在`ChannelInitializer`中,我们指定了我们的`ServerHandler`来处理连接。在客户端中,我们创建了一个`Socket`并发送"Hello Server!"字符串到服务器。获取服务器响应并将其输出到控制台。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值