C/C++ socket通信 服务端 客户端相互发送消息(一人一句)

C/C++ socket通信 服务端 客户端相互发送消息(一人一句)

server.cpp

服务端代码如下
server.cpp

#include<iostream>
#include<stdio.h>
#include<Winsock2.h>
#include<fstream>
using namespace std;
int main()
{

    WORD wsa = MAKEWORD(2,2);
    //这里声明了winsock的版本2.2
    //1.1版本只支持TCP/IP协议
    //2.0版本支持多协议。
    //2.0版有兼容性
    //任何使用1.1版的源代码、二进制文件、应用程序都可以不加修改地在2.0规范下使用
     WSADATA wsaData;
     //WSADATA结构体中主要包含了系统所支持的Winsock版本信息
     if(WSAStartup(wsa, &wsaData)!=0)
    {
        cout<<"初始化失败"<<endl;   //这进行初始化
        return 0;
    }
    //创建套接字
    SOCKET s_server = socket(AF_INET, SOCK_STREAM, 0);
    //AF_INET   面向网络的  IPV4
    //AF_INET6用于第6版因特网协议(IPv6)寻址
    //SOCK_STREAM   TCP链接   面向链接    SOCK_DGRAM 无连接 UDP
    if(s_server==INVALID_SOCKET) //INVALID_SOCKET是-1 错误标志
    {
        cout<<"socket创建失败"<<endl;
        return 0;
    }
    //这里配置server配置信息
    sockaddr_in server_addr;    //创建sockaddr_in结构体
    server_addr.sin_family = AF_INET;   //IPV4协议
    server_addr.sin_port = htons(8888);     //本地端口8888
    server_addr.sin_addr.S_un.S_addr = INADDR_ANY;   //设置地址 监听本地端口
    //利用bind函数将socket和配置信息绑定
    //bind通常和下面的listen配套使用 处于被动链接中泰
    if   (  bind( s_server,(SOCKADDR *)&server_addr,sizeof(SOCKADDR)) ==SOCKET_ERROR )
    {
        //socket和配置绑定
        cout<<"ERROR bind!!"<<endl;
        WSACleanup();
    }

    if(listen( s_server,5 )<0)
    {
        cout<<"监听失败"<<endl;
    }
    cout<<"listen********************"<<endl;
    sockaddr_in clinet_addr;   //用于获取客户端地址端口信息 用于回传
    SOCKET s_accept;
    //这里定义了一个用于接收的sockaddr_in名字为s_accept。用于接收客户端的地址信息和端口信息,用于回传。
    int len=sizeof(SOCKADDR);
    s_accept = accept(s_server,(SOCKADDR *)&clinet_addr,&len);
    //在这里阻塞 挂起等待
    
    if( s_accept ==SOCKET_ERROR  )  //
    {
        cout<<"connect error"<<endl;
        return 0;
    }
    cout<<"connection is OK;ready to accept"<<endl;
    char recv_buf[100];
    char send_buf[100];
    //两个buff缓冲区,用于缓存接收字符和发送字符。
    while(1)
    {
        int recv_len= recv(s_accept,recv_buf,100,0);
        //这里 即使链接断开 也能继续监听 服务端不关闭
        if(recv_len<0)
        {
            cout<<"listen********************"<<endl;
            s_accept = accept(s_server,(SOCKADDR *)&clinet_addr,&len);
            //在这里阻塞 挂起等待
            continue;
            if( s_accept ==SOCKET_ERROR  )  //
            {
                cout<<"connect error"<<endl;
                return 0;
            }
        }
        cout<<"客户端消息"<<recv_buf<<endl;


        cout<<"输入服务端消息"<<endl;
        cin>>send_buf;
        send(s_accept,send_buf,100,0);
        cout<<"发送成功"<<endl<<endl;

    }
    closesocket(s_server);
	closesocket(s_accept);
	//释放DLL资源
	WSACleanup();
	return 0;
}

client.cpp

#include<iostream>
#include<stdio.h>
#include<Winsock2.h>
using namespace std;
int main()
{

    WORD wsa = MAKEWORD(2,2);
    //这里声明了winsock的版本2.2
    //1.1版本只支持TCP/IP协议
    //2.0版本支持多协议。
    //2.0版有兼容性
    //任何使用1.1版的源代码、二进制文件、应用程序都可以不加修改地在2.0规范下使用
     WSADATA wsaData;
     //WSADATA结构体中主要包含了系统所支持的Winsock版本信息
     if(WSAStartup(wsa, &wsaData)!=0)
    {
        cout<<"初始化失败"<<endl;   //这进行初始化
        return 0;
    }
    SOCKET s_server = socket(AF_INET, SOCK_STREAM, 0);
    if(s_server==INVALID_SOCKET)
    {
        cout<<"socket创建失败"<<endl;
        return 0;
    }
    sockaddr_in server_addr;
    server_addr.sin_family = AF_INET;   //IPV4协议
    server_addr.sin_port = htons(8888);     //服务器端口
    //这里有改动 写网络地址
    server_addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
    if (connect(s_server, (SOCKADDR *)&server_addr, sizeof(SOCKADDR)) == SOCKET_ERROR) {
		cout << "server connnet fail!!" << endl;
		WSACleanup();
		return 0;
	}
	else {
		cout << "success!!" << endl;
	}
    system("pause");
     char send_buf[200];
        char accept_buf[200];
    while(1)
    {

        cout<<"input your message:"<<endl;
        cout<<endl;
        cin>>send_buf;
        int res_len = send(s_server,send_buf,100,0);
        if(res_len<0)
        {
            cout<<"error"<<endl;
        }
        cout<<"发送成功,等待接受"<<endl;
       recv(s_server, accept_buf, 200, 0);
       cout<<"服务端消息"<<accept_buf<<endl;

        cout<<"接受成功"<<endl<<endl;

    }

    closesocket(s_server);
	//释放DLL资源
	WSACleanup();
	return 0;
}

解析如下

在这里插入图片描述
首先是服务端
这里有s_server 对于服务端SOCKET接口的创建
AF_INET 域socket通信过程 典型的TCP/IP四层模型的通信过程。
使用IPV4通信
SOCK_STREAM作为TCP链接,面向链接
SOCK_DGRAM 则无连接 UDP
在这里插入图片描述
接下来是配置本地的服务信息,包括协议 端口 和 地址
利用bind函数将socket和配置信息绑定
在这里插入图片描述
接下俩是listen函数,旨在一个socket的句柄上监听链接。
该函数在bind之后,在accept之前。用于从一个主动链接转化称被动链接,作为服务端。
在这里插入图片描述
这里定义了一个用于接收的sockaddr_in名字为s_accept。用于接收客户端的地址信息和端口信息,用于回传。
在这里插入图片描述
两个buff缓冲区,用于缓存接收字符和发送字符。
在这里插入图片描述
死循环,阻塞等待
在这里插入图片描述
这里,我让他如果客户端断开链接,那么重新阻塞等待新的client链接,获取新的客户端地址和端口等

这里输出recv函数获取的缓存信息(recv_buf)
输入send_buf
利用send函数发出去。
在这里插入图片描述
释放和清空。

客户端:
客户端大致一样。
在这里插入图片描述
这里填入服务器端口信息和服务器地址。
利用send函数和recv函数

运行结果如下
在这里插入图片描述
服务端
在这里插入图片描述
客户端链接成功
在这里插入图片描述
客户端输入信息 回车后发送
在这里插入图片描述
服务端接收
在这里插入图片描述
服务端接收数据后 写入信息 回车后发送给客户端

虚拟机(模拟非本地链接)调试如下:
在这里插入图片描述
虚拟机利用桥接模式,逻辑上和主机同网段
在这里插入图片描述

服务端IP 192.168.137.30
在这里插入图片描述
虚拟机IP

在这里插入图片描述
服务端用INADDR_ANY不变
在这里插入图片描述
客户端填入192.168.137.30 即服务端IP
在这里插入图片描述
这里服务端关闭防火墙(否则根据安全策略,对外丢弃非白名单端口的数据包),当然也可以更改安全策略,这里为了简便就不更改了
在这里插入图片描述
虚拟机链接成功
在这里插入图片描述
数据交换成功

在这里插入图片描述
链接建立

  • 12
    点赞
  • 76
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值