vc6.0 简易的tcp网络讲解(二)

至于为什么用vc6.0,我用的是xp系统,没钱

有错误请指出,本人业余的(所写的代码,尽量注释清楚)通过vc6.0的直接复制粘贴即可

(代码来源于网络,

仅供学习交流,严禁用于商业用途

本人参考的大神的代码,这个代码写的比较简单易懂!推荐大家先去看看(看完再看我的,容易理解)

http://blog.csdn.net/lcytrl/article/details/7896073

下面代码复杂了点,我对别人的代码是进行了解释,能看就看看吧!

服务器端

////////////////服务器端代码 sever.cpp  
///一、初始化套接字  
///二、创建套接字  
///三、绑定  
///四、侦听  
///五、接收  
///六、发送  
///七、销毁连接  
////////////////////////////////////////////////////  
  
#include <iostream>  
#include <WINSOCK2.H>  
//#include <cstdlib>  
#pragma comment(lib,"WS2_32.lib")  
using namespace std;  
  
#define SER_PORT 5000       //预定义端口定义  
#define SER_IP "127.0.0.1"  //预定义的IP   此IP是测试专用自发自收IP,详情百度哈,当然,也可以转发测试
  
DWORD WINAPI ThreadProcessor(LPVOID lpParameter); //接收数据的线程函数  //后面笔记会讲到(不用理解)
fd_set fdRead = {0};  
  
int main()  
{  
    SOCKET sever;    ///定义套接字  描述一个数值,跟定义int  sever差不多;注意区别
    SOCKET client;            //socket 网络中,只能用socket定义一些值
    char buf[1024];  
    SOCKADDR_IN ser_addr;   //服务器地址信息 (指定ser_addr) (至于用法,我大概知道什么意思)
                            //(不太懂的话,好好学习结构体,和百度)
    
    SOCKADDR_IN cli_addr;    //客户端地址信息  
    //HANDLE hnd;     
    int ret;   //用于保存函数返回值  
    WORD wVersionRequested;                       //  ↓启动版本
    WSADATA wsaData;  
    int cliAddrLen;                               //  ↓2.2版本(至于有什么区别我也不知道,大家百度)
    wVersionRequested=MAKEWORD(2,2);  
    if(WSAStartup(wVersionRequested,&wsaData)!=0) //
    {  
        cout << "初始化失败!\n";                 //  ↑大致就是启动函数
        return 1;  
    }                                             //
    ser_addr.sin_family = AF_INET;  
    ser_addr.sin_addr.S_un.S_addr = inet_addr(SER_IP);  //输入IP地址
    ser_addr.sin_port = htons(SER_PORT);                //输入端口地址
    memset(ser_addr.sin_zero,0,8);                  
    ///创建套接字  
    sever = socket(AF_INET,SOCK_STREAM,0);  //如果绑定ip和端口成功,应该返回一个值//
    //
    if (sever == INVALID_SOCKET)            //一般很难创建失败,除非前面写程序有错误,改ip和端口
    {  
        cout << "创建套接字失败!\n";       //直接在预定义改,比较方便
        return 1;  
    }  
    //绑定  
    if(bind(sever, (SOCKADDR *)&ser_addr, sizeof(SOCKADDR)) != 0)  //sizeof()函数 取出地址结构长度
    {  
        cout << "绑定失败!\n";  
        return 1;  
    }  
    else  
    { cout << "服务器端已成功启动......\n\n"; }  
  
/****下面是绑定的结构图
    int bind (
  SOCKET s,                          //要绑定的套接字
  const struct sockaddr FAR*  name,  //指定了该套接字的本地地址信息
  int namelen                        //该地址结构的长度
);
****/
//到此上面所有的步骤完成,代表了开启了服务器、、有什么不动可以查看我的参考网址

    while (1)   //服务器端继续搜索新的连接  
    {  
          //侦听  
        if (int i = listen(sever,6) != 0)                //一般防火墙和某些软件冲突
                                                         //一般不会影响的侦听
        {  
            cout << "侦听失败: " << WSAGetLastError() <<endl;  
            return 1;  
        }  
        cliAddrLen = sizeof(SOCKADDR);   //sizeof()函数 取出地址结构长度 
        //返回客户端套接字   cli_addr 为客户端的地址及端口信息  
        if((client = accept(sever,(SOCKADDR *)&cli_addr,&cliAddrLen)) == INVALID_SOCKET)   //这里阻塞了。 
        {  
            cout << "客户端已经断开连接!\n\n";                               //如果accept()没有找到客户端
            break;                                                           //应该是一直卡在里面
        }                                                                   //
        cout << "Client Ip: " << inet_ntoa(cli_addr.sin_addr) << endl;  //出现了客服端,自动进行打印
        cout << "Client Port: " << ntohs(cli_addr.sin_port) << endl;    //客户端IP和端口
  
//      ULONG ul=1;  
        ///阻塞控制,用了selec选择就不需要用此函数了  
//      if (ret=ioctlsocket(client,FIONBIO,&ul) == SOCKET_ERROR)  
//      {  
//          cout << "Call ioctlsocket function fail !\n";  
//          return 1;  
//      }  
          
        FD_ZERO(&fdRead);  //清空集合  
        FD_SET(client,&fdRead); //将client加入到读取集合中  
  
        bool bAvail = true;  
        ///接收数据  
        while( bAvail )  
        {  
            FD_SET(client,&fdRead); //将client加入到读取集合中  
      
            ///缓冲区里有可读数据才返回,不然阻断程序  
            timeval t = {0};  
            t.tv_usec = 10000*500;  
            char sendBuf[1024];  
            if ( (ret = select(0,&fdRead,NULL,NULL,&t)) <= 0 )  //阻塞控制 读取数据才向下 
            {  
                continue;  //结束循环//这里继续向下
            }  
            if (ret>0)  
            {  
                if (FD_ISSET(client,&fdRead))  //client in fdRead  
                {         
                    int RecvBytes=0;  
                    do   //循环读取数据,直到缓冲区中的数据读完-   这个可能有错误  
                    {  
                        //接收数据  
                        RecvBytes = recv(client,buf,sizeof(buf),0);     //读取数据放到RecvBytes
                        if (RecvBytes==SOCKET_ERROR || RecvBytes == 0)  //查询,是否一直在连接
                        {  
                            cout << "数据接收失败或客户端已经断开!\n";  
                            bAvail = false;  
                            break;  
                        }  
            //c语言里面字符串结束符'\0'的值就是0,所以buf[buf_len] = 0; 通buf[buf_len] = '\0';
                        buf[RecvBytes] = 0; //给数据串加上结束符  
                        //打印收到数据  
                        cout << "收到" << RecvBytes <<" bytes 数据:  "  
                             << buf <<endl;  
                        cout << "发送: ";  
                        cin.getline(sendBuf,1024);             //相当于阻断,等到接受数据,并按下确定
                        ///向客户端发送数据  
                        if(send(client,sendBuf,strlen(sendBuf),0) ==-1)  
                            return -1;  
                        Sleep(2*1000);  
                    } while (RecvBytes>0);     
                }  
            }  
            FD_ZERO(&fdRead);  
        }//while  
        closesocket(client);  
   }//while  
      
    cout << "end\n";  
    Sleep(5000);  
  
    FD_CLR(client,&fdRead);  
    closesocket(sever);  
    WSACleanup();  
    return 0;  
}  
View Code

客服端

#include <iostream>  
#include <WINSOCK2.H>  
#include <cstring>  
#pragma comment(lib,"WS2_32.lib")  
using namespace std;  
  
#define DES_IP "122.114.122.174"  
#define DES_PORT 38111 
//#define DES_IP "127.0.0.1"  
//#define DES_PORT 5000  
  
int main()  
{  
    SOCKET sock;  
    char buf[1024]; //发送的字串  
    SOCKADDR_IN ser_addr;  
    WSADATA wsaData;  
    WORD wVersionRequired;  
    wVersionRequired = MAKEWORD(2,2);  
    if (WSAStartup(wVersionRequired,&wsaData)!=0)  
    {  
        cout<<WSAGetLastError()<<endl;  
        cout << "初始化失败!\n";  
    //  return 1;  
    }  
  
    //if (sock = WSASocket(AF_INET,SOCK_STREAM,IPPROTO_IP,NULL,0,1))  
    // 创建套接字两种方式  
    sock = socket( AF_INET, SOCK_STREAM, 0 );  
//  if (sock = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP)==INVALID_SOCKET)  
//  {  
//      cout << "创建套接字失败!\n\n";  
//      return 1;  
//      }  
  
    ser_addr.sin_addr.S_un.S_addr = inet_addr(DES_IP);  
    ser_addr.sin_port = htons(DES_PORT);  
    ser_addr.sin_family = AF_INET;  
    memset(ser_addr.sin_zero,0,8);  
    //连接  
    if (connect(sock,(SOCKADDR *)&ser_addr,sizeof(SOCKADDR_IN))!=0)  
    {  
        int nError = WSAGetLastError();  
        cout << "连接服务器端失败\n";  
        return 1;  
    }  
    else   
    {  
        cout << "成功连接服务器,可以开始发送数据,输入\"exit\"时断开连接\n\n";  
    }  
    //发送数据  
    do   
    {  
        int SentBytes;  
        int RecvBytes;  
        char strRecv[1024] = {0};  
        cout << "发送:";  
        cin >> buf;  
        if(strcmp(buf,"exit") ==0 ) break;  
        SentBytes = send( sock,buf, strlen(buf), 0 );  
        if (SentBytes == SOCKET_ERROR)   ///发送失败  
        {  
            cout << "发送数据失败!\n\n";  
            break;  
        }  
//      else //发送成功  
//      {  
//          cout << buf <<endl;  
//      }  
        if ((RecvBytes = recv(sock,strRecv,sizeof(strRecv),0)) != SOCKET_ERROR)  
        {  
            strRecv[RecvBytes] = 0;  
            cout << "接收: " << strRecv << endl;  
        }  
        else  
        {  
            cout << WSAGetLastError() <<endl;  
            cout << "接收数据失败!\n";  
        }  
         Sleep(1000);  
    } while (1);  
    closesocket(sock);  
    WSACleanup();  
    return 0;  
}
View Code

这里说明以下,只是作为理解讲解,主要还是看上面那个网站

下面是运行效果(BUG只能接受到了,才能发送,如果没有接受到,就发送不了,但要发送的数据会被保存在缓冲中,等待着下次收到发送时,一并打出)(BUG都是程序不完善引起)

posted on 2018-03-12 23:22  爱学习的蝈蝈  阅读(515)  评论(0编辑  收藏  举报

导航