朋友,请你不要担心自己不懂,写这篇博客的时候,我们都一样,我也对其中的一些知识点不甚了解。
这里用的是两个进程模式(2个主程序),一个客户端,一个服务器端。
本文的 socket 编程之所以定义为转载,是因为我引用了前辈们大量的总结,但是, 以下的代码都是在 vs2012 win32 环境下编译
通过的,可以直接拷贝到 Windows 下的相关环境里运行。
客户端:
/*
coder: meson;
date:2018/9/2;
function: Client in sockets;
*/
#include <iostream>
#include <WinSock2.h>
using namespace std;
#pragma comment(lib,"ws2_32.lib")
void main()
{
/*-----------------------------版本请求确认-----------------------------*/
WORD wVersionRequested; //Requested Version
WSADATA wsaData; //用来存储 被WSAStartup函数调用后返回的 Windows Sockets 数据
int err;
wVersionRequested = MAKEWORD(2,2);
err =WSAStartup( wVersionRequested,&wsaData);
//使用Socket之前必须调用WSAStartup函数
//当一个应用程序调用WSAStartup函数时,操作系统根据请求的Socket版本来搜索相应的Socket库,然后绑定找到的Socket库到该应用程序中。以后应用程序就可以调用所请求的Socket库中的其它Socket函数了。该函数执行成功后返回0。
if( err != 0)
{
//tell the user that we could nto find a usable
//WinSock DLL;
return;
}
if(LOBYTE(wsaData.wVersion)!=2||HIBYTE(wsaData.wVersion)!=2)
{
WSACleanup();
return;
}
//The WinSock DLL is acceptable,Proceed windows下版本的协商
/*--------------------创建一个socket并连接Socket address(在服务器上)--------------------*/
SOCKET sockCli;//client socket
sockCli = socket(AF_INET,SOCK_STREAM,0);//创建套接字 家族协议;流式套接字;默认值
SOCKADDR_IN addrSer;//Socket address, internet style is ipv4.
addrSer.sin_family = AF_INET; //家族协议
addrSer.sin_port = htons(5050); //端口
addrSer.sin_addr.S_un.S_addr = inet_addr ("192.168.228.39"); //与服务器ip地址一致
int res = connect(sockCli,(SOCKADDR*)&addrSer,sizeof(SOCKADDR));
//res为connect返回值 查阅相关函数,若为0则表示没有错误
//SOCKADDR表示socket的协议地址(通用结构),SOCKADDR_IN是具体实例——ipv4,SOCKADDR_IN6为ipv6.
if (res != 0)
{
cout<<"Client Connect Servrer Fail!"<<endl;
return;
}
else
{
cout<<"Client Connect Servrer Success!"<<endl;
}
/*-----------------------------发送、接收数据-----------------------------*/
char sendbuf[256]={};
char recvbuf[256]={};//发空间和接收空间
while(1)
{
cout<<"Cli:_____________________"<<endl;
cin>>sendbuf;
if(strcmp(sendbuf,"quit") == 0)//客户端请求退出
{
break;
}
send(sockCli,sendbuf,strlen(sendbuf)+1,0);
recv(sockCli,recvbuf,256,0);
cout<<"Ser:_____________________"<<endl;
cout<<recvbuf<<endl;
}
/*-----------------------------关闭socket,析构资源-----------------------------*/
closesocket(sockCli);
WSACleanup();
}
服务器端:
/*
coder: meson;
date:2018/9/2;
function: Client in sockets;
*/
#include <iostream>
#include <WinSock2.h>
using namespace std;
#pragma comment(lib,"ws2_32.lib") //引用静态链接库
void main()
{
/*-----------------------------版本请求确认-----------------------------*/
WORD wVersionRequested; //Requested Version
WSADATA wsaData; //用来存储 被WSAStartup函数调用后返回的 Windows Sockets 数据
int err;
wVersionRequested = MAKEWORD(2,2);
err =WSAStartup( wVersionRequested,&wsaData);
//使用Socket之前必须调用WSAStartup函数
//当一个应用程序调用WSAStartup函数时,操作系统根据请求的Socket版本来搜索相应的Socket库,然后绑定找到的Socket库到该应用程序中。以后应用程序就可以调用所请求的Socket库中的其它Socket函数了。该函数执行成功后返回0
if( err != 0)
{
//tell the user that we could nto find a usable
//WinSock DLL;
return;
}
if(LOBYTE(wsaData.wVersion)!=2||HIBYTE(wsaData.wVersion)!=2)
{
WSACleanup();
return;
}
//The WinSock DLL is acceptable,Proceed windows下版本的协商
/*--------------------创建一个server socket并bind and listen--------------------*/
SOCKET sockSer; //server socket
sockSer = socket(AF_INET,SOCK_STREAM,0);
//创建套接字,AF_INET代表IP家族,0是默认的方式创建 有连接是流式 无连接是数据包套接字
SOCKADDR_IN addrSer; //server socket address
addrSer.sin_family = AF_INET;
addrSer.sin_port = htons(5050);
addrSer.sin_addr.S_un.S_addr = inet_addr("192.168.228.39");
bind(sockSer,(SOCKADDR*)&addrSer,sizeof(SOCKADDR));
//绑定套接字 server socket is binded to server socket address
//SOCKADDR表示socket的协议地址(通用结构),SOCKADDR_IN是具体实例——ipv4,SOCKADDR_IN6为ipv6.
listen(sockSer,5);
//将sockSer设为监听模式 最长队列大小为5
/*--------------accept,发送、接收数据 accept成功后可以开启一个新线程or进程--------------*/
SOCKET sockConn;
//用于保存accept()返回的socket 它就像文件打开后返回的句柄,server端的I/O操作都基于它
SOCKADDR_IN addrCli;
//用于保存client socket address (accept()函数会将接收到的客户端信息存于addrCli)
int len = sizeof(SOCKADDR);
cout<<"Server Wait Client Connect......."<<endl;
sockConn = accept(sockSer,(SOCKADDR*)&addrCli,&len);
//处理新到连接 3个参数分别是服务器的套接字号;客户端地址,地址长度的地址
if(sockConn == INVALID_SOCKET)
{
cout<<"Server Accept Client Connect Fail"<<endl;
return;
}
else
{
cout<<"Server Accept Client Connect Success"<<endl;
}
//INVALID_SOCKET非法套接字
char sendbuf[256]={};
char recvbuf[256]={};
//用于发送、接收数据的缓存
while(1)
{
recv(sockConn,recvbuf,256,0);//接收
cout<<"Cli:_____________________"<<endl;
cout<<recvbuf<<endl;
cout<<"Ser:_____________________"<<endl;
cin>>sendbuf;//缓冲区
if(strcmp(sendbuf,"quit")==0)//相等表示服务器请求退出
{
break;
}
send(sockConn,sendbuf,strlen(sendbuf)+1,0);
//发送服务器 +1为了字符串的"\0" 3个参数分别是要发送的套接字,缓冲,长度
}
closesocket(sockConn); //关闭socket
/*-----------------------------关闭初始的socket,析构资源-----------------------------*/
closesocket(sockSer);
WSACleanup(); //清除版本信息
}