C++ socket notes

朋友,请你不要担心自己不懂,写这篇博客的时候,我们都一样,我也对其中的一些知识点不甚了解。

这里用的是两个进程模式(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();			//清除版本信息
}

猜你喜欢

转载自blog.csdn.net/A_Pointer/article/details/82261655