学习笔记 c++ (socket编程 一对多通信)

/*1 一对多模型,TCP的编程步骤

服务端:
1、socket()获得一个sockfd。注意第二个参数必须SOCK_STREAM.
2、准备通信地址(必须服务器的)
3、bind()绑定。(开放了端口,允许客户端连接)
4、监听客户端 listen()函数
5、等待客户端的连接 accept(),返回用于交互的socket描述符
6、使用第5步返回sockt描述符,进行读写通信。
7、关闭sockfd。

客户端:
客户端的代码与一对一的一样。注意第二个参数必须SOCK_STREAM.

TCP一对多模型,有两类描述符:
第一步的描述符不再参与信息交互,只是等待客户端的连接(accept),accept()在客户端连接上来后,会返回一个新的描述符,用于读写通信。
*/

// 服务器代码

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

using namespace std;

int main()
{    
    //1.socket()获得一个sockfd。注意第二个参数必须SOCK_STREAM.
    //第一个参数是地址描述符,常用AF_INET(表示IPV4)
    //第三个参数是套接口所用的协议,不想调用就用0
    int socket_fd = socket(AF_INET,SOCK_STREAM,0);
    if(socket_fd == -1)
    {
        cout<<"socket 创建失败:"<<endl;
        exit(-1);
    }

    //2.准备通讯地址(必须是服务器的)
    //sin_family:协议簇一般用AF_INET(表示IPV4)
    //sin_port: 端口,一般用htons(填端口:数字随便要和服务器的一样)将十进制转为网络进制
    //sin_addr.s_addr:一般用inet_addr(" "填IP地址)
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(8888);
    addr.sin_addr.s_addr = inet_addr("192.168.1.137");

    //3.bind() 绑定。(开发了端口,允许客服端链接)
    //参数一:0的返回值(socket_fd)
    //参数二:(struct sockaddr*)&addr 前面结构体,即地址
    //参数三: addr结构体的长度
    int res = bind(socket_fd,(struct sockaddr*)&addr,sizeof(addr));
    if(res == -1)
    {
        cout<<"bind 创建失败:"<<endl;
        exit(-1);        
    }
    cout<<"bind ok 等待客户端的连接"<<endl;
    
    //4.监听客户端 listen()函数
    //参数二:进程上限,一般小于30
    listen(socket_fd,30);
    
    //5.等待客户端的连接 accept(),返回用于交互的socket描述符
    struct sockaddr_in client;
    socklen_t len = sizeof(client);
    int fd = accept(socket_fd,(struct sockaddr*)&client,&len);
    if(fd == -1)
    {
        printf("accept 错误\n");
        exit(-1);
    }

    //6.使用第5步返回sockt描述符,进行读写通信。
    char *ip = inet_ntoa(client.sin_addr);
    cout<<"客户:【"<<ip<<"】链接成功"<<endl;

    char buffer[255] = {};
    int size = read(fd, buffer, sizeof(buffer));
    //第一个参数:accept 返回的文件描述符
    //第二个参数:存放读取的内容
    //第三个参数:内容的大小    
    
    cout<<"接收到字节数为:"<<size<<endl;
    cout<<"内容:"<<buffer<<endl;
    write(fd,"welcome",7);

    //7.关闭sockfd。
    close(fd);
    close(socket_fd);
    return 0;
}

 

// 客服端代码

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

using namespace std;

int main(int argc, char** argv)
{
    int socket_fd = socket(AF_INET, SOCK_STREAM,0);
    if(socket_fd == -1)
    {
        cout<<"socket 创建失败:"<<endl;
        exit(-1);
    }
    
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(8888);
    addr.sin_addr.s_addr = inet_addr("192.168.1.137");
    
    int res = connect(socket_fd,(struct sockaddr*)&addr,sizeof(addr));
    if(res == -1)
    {
        cout<<"bind 链接失败:"<<endl;
        exit(-1);
    }
    cout<<"bind 链接成功:"<<endl;
    
    write(socket_fd,"hello lichao",5);
    
    close(socket_fd);

    return 0;
}

 

 

上面的服务端还只是实现了一对一的通信,一对多通信加一个while循环即可。

 

实现客服端输入发送,服务器接收并回应

server.cpp

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

using namespace std;

int main()
{    

    //1.socket()获得一个sockfd。注意第二个参数必须SOCK_STREAM.
    //第一个参数是地址描述符,常用AF_INET(表示IPV4)
    //第三个参数是套接口所用的协议,不想调用就用0
    int socket_fd = socket(AF_INET,SOCK_STREAM,0);
    if(socket_fd == -1)
    {
        cout<<"socket 创建失败:"<<endl;
        exit(-1);
    }

    //2.准备通讯地址(必须是服务器的)
    //sin_family:协议簇一般用AF_INET(表示IPV4)
    //sin_port: 端口,一般用htons(填端口:数字随便要和服务器的一样)将十进制转为网络进制
    //sin_addr.s_addr:一般用inet_addr(" "填IP地址)
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(8888);
    addr.sin_addr.s_addr = inet_addr("192.168.1.137");

    int reuseaddr = 1;//解决地址已被占用问题
        setsockopt(socket_fd,SOL_SOCKET,SO_REUSEADDR,&reuseaddr,sizeof(reuseaddr));

    //3.bind() 绑定。(开发了端口,允许客服端链接)
    //参数一:0的返回值(socket_fd)
    //参数二:(struct sockaddr*)&addr 前面结构体,即地址
    //参数三: addr结构体的长度
    int res = bind(socket_fd,(struct sockaddr*)&addr,sizeof(addr));
    if(res == -1)
    {
        cout<<"bind 创建失败:"<<endl;
        exit(-1);        
    }
    cout<<"bind ok 等待客户端的连接"<<endl;

  while(1)
  {    

    //4.监听客户端 listen()函数
    //参数二:进程上限,一般小于30
    listen(socket_fd,30);
    
    //5.等待客户端的连接 accept(),返回用于交互的socket描述符
    struct sockaddr_in client;
    socklen_t len = sizeof(client);
    int fd = accept(socket_fd,(struct sockaddr*)&client,&len);//阻塞函数
    if(fd == -1)
    {
        printf("accept 错误\n");
        exit(-1);
    }

    //6.使用第5步返回sockt描述符,进行读写通信。
    char *ip = inet_ntoa(client.sin_addr);

    cout<<"客户:【"<<ip<<"】链接成功"<<endl;
    //写给服务器的回应
    write(fd,"欢迎来到李超的服务器",100);

    char buffer[255] = {};
    int size = read(fd, buffer, sizeof(buffer));
    //第一个参数:accept 返回的文件描述符
    //第二个参数:存放读取的内容
    //第三个参数:内容的大小    
    
    //cout<<"接收到字节数为:"<<size<<endl;
    cout<<"内容:"<<buffer<<endl;

 

    //7.关闭sockfd。
    close(fd);

  }
    close(socket_fd);
    return 0;
}

 

client.cpp

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

using namespace std;

int main(int argc, char** argv)
{    
  while(1)
  {
    int socket_fd = socket(AF_INET, SOCK_STREAM,0);
    if(socket_fd == -1)
    {
        cout<<"socket 创建失败:"<<endl;
        exit(-1);
    }
    
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(8888);
    addr.sin_addr.s_addr = inet_addr("192.168.1.137");

    int res = connect(socket_fd,(struct sockaddr*)&addr,sizeof(addr));
    
    if(res == -1)
    {
        cout<<"bind 链接失败:"<<endl;
        exit(-1);
    }
    cout<<"bind 链接成功:"<<endl;
    //读取服务器的回应
    char buff[100] = {};    
      read(socket_fd,buff,sizeof(buff));
    cout<<buff<<endl;

    char a[100] = {};
    int c=100;
    cout<<"请发送你的消息:";
    //string hh;
    cin.getline(a,c);    
    write(socket_fd,a,sizeof(a));
    cout<<"成功发送内容:"<<a<<endl;

    close(socket_fd);
  }
    return 0;
}

执行结果

 

 

 

 

 

 

 

 

 

 

 

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值