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
这里服务端关闭防火墙(否则根据安全策略,对外丢弃非白名单端口的数据包),当然也可以更改安全策略,这里为了简便就不更改了
虚拟机链接成功
数据交换成功
链接建立