windows scoket类编写

INVALID_SOCKET 无效网络套接字;

在windows上演示需要添加一个库:

 

::recv(Socket,recvBuf,BUFFERMAXSIZE,0);

第一个参数是建立的socket

第二个参数是用来存储的recv数据的buf

第三个参数是允许最大的接收size而不是buf的size 但是buf的size一定要大于允许最大的接收size

第四个参数是设置recvtimeout用好像是

主要说两点

一是当server发送数据调用send函数时,调用成功只是把该部分数据拷贝到发送缓冲区,接下来的工作是由Tcp/Ip协议发送数据的。

当server端的数据比Client端的数据长时 client端recv时是多包的

len = ::recv(Socket,recvBuf,BUFFERMAXSIZE,0);

if(len == BUFFERMAXSIZE)还可以接着recv直到len < BUFFERMAXSIZE

二是当len= -1时,可能是socket关闭。

还有当建立的是TCP连接时,网络断开是recv是可以检测到的返回len = -1所以不用担心会挂起在recv中。

 

 

 

 

判断是windows系统还是linux系统:

#ifdef WIN32

#include <WinSock2.h>

#else

//linux

#endif

 

 

Socket必备;

1.      要写一个监听的接口:listen:

2.      是否已连接的接口:isConnected;

3.      Connect()客户端通过ip连接服务器的接口;

4.      发送数据的接口;send()

5.      是否接收数据的接口;recvStart();

6.      是否接收完了的接口;recvComplete();

7.      接收数据长度的接口:RecvData();

 

//实现监听listen(shor port);

{

SOCKET sock = socket(AF_INET,SOCK_STREAM,0);//设置为ipv4的流文件传输;

然后做个判断:

If(scok == INVALID_SOCKET) return         false;

 

然后绑定端口:

1.      先写好ip和ip类型和端口;struct

Struct scoketaddr_in addr;//结构体定义;

Addr.family = AF_INET;//协议类型;

Addr.sin_port = htons(port);//端口;

Addr.sin_addr.S_un.S_addr = INADDR_ANY;//ip地址;  INADDR_ANY = 0.0.0.0;

2.      开始绑定:

Int ret = bind(sock,(struct sockaddr*)&addr,sizeof(addr));//绑定socket接口和ip地址,和长度;

 

然后对绑定进行错误判断:

If(ret != 0)

{

         Closesocket(sock);

         Returnfalse;

}

 

//监听连接数;

listen(sock,10);

 

启动socket网络之前先要连接服务器,所以把服务器赋值好;

_server = sock;

//在启动线程之前,让链接判断为0;

_isConnected = 0;

 

Windows下起线程,;

HANDLE hThread =CreateThread(NULL,0,AcceptThreadFunc,NULL,0,NULL);//创建线程;

CloseHandle(hThread);

 

Return true;

 

}

 

这个现场链接服务器;

//复写线程的函数;

DWORD net::AcceptThreadFunc(void * arg)

{

         _connect = accept(_server,NULL,NULL);

         //进入这里的时候线程启动,isconnect为1;

_isConnected =1;

         //DWORD的返回类型是无符号长整型,unsigned     long         int;

         Return0;

}

 

//是否链接;

Bool net::isConnected()

{

         Return(bool)_isConnected;

}

 

客户端的socket写法;//服务器的listen监听只有一个端口;short port;

这里是客户端去连服务器,所以要有个对准服务器的ip地址;

Bool net::Connect(const char * ip,shorport)

{

         _connect= socket(AF_INET,SOCK_STEAM,0);//协议类型ipv4文件流;

 

         //再来个判断;

         If(_connect== INVALID_SOCKET) return false;

 

         //链接的话需要ip地址和端口;

         Structsockaddr_in addr;

         Addr.sin_family= AF_INET;

         Addr.sin_port= htons(port);

         Addr.sin_addr.S_un.S_addr= inet_addr(ip);

        

         //connect;

         Intret = connect(_connect,(struct sockaddr *)&addr,sizeof(addr));//服务器绑定和客户端连接时一样写的;

         If(ret!= 0)

{

         Closesocket(_connect);

         Return false;

}

//链接成功;

Return false;

}

 

开始接收数据;

Bool net::RecvStart()

{

         //这里调用recvstart会阻塞,所以要用线程,实际程序的接收是在线程里;

         _isRecvComplete= 0;

         HANDLEhThread = CreateThread(NULL,0,RecvThreadFunc,NULL,0,NULL);//创建线程;

         CloseHandle(hThread);

Return true;

}

DWORD net::RecvThreadFunc(void * arg)

{

         Staticchar * buf[16];

         Recv(_connect,buf,1,0);

_recvData = buf;

_isRecvComplete = 1;

Return 0;

}

 

//数据接收成功;

Bool net::isRecvComplete()

{

         Return(bool)_isRecvComplete;

}

Char * net::RecvData(int & len)

{

Len = 0;

_isRecvComplete = 0;

Return _recvData;

}

Int net::Send(const char * buffer,int len)

{

         Returnsend(_connect,buffer,len,0);

}

.cpp:


#include "Net.h"
 
SOCKET Net::_server =INVALID_SOCKET;//INVALID_SOCKET表示无效的socket:
SOCKET Net::_connect = INVALID_SOCKET;
 
int Net::_isConnected = 0;
int Net::_isRecvComplete = 0;
 
char * Net::_recvData = NULL;
 
bool Net::Listen(short port)
{
         //写一个SOCKET接口变量附上协议类型;
         SOCKETsock = socket(AF_INET, SOCK_STREAM, 0);
         //如果协议都错了的话就不让登陆;
         if(sock = INVALID_SOCKET){
                   CCLog("sockfail");
                   returnfalse;
         }
 
         //绑定端口;写地址结构体;
         structsockaddr_in addr;
         //地址类型IPV4;
         addr.sin_family= AF_INET;
         //转换端口;
         addr.sin_port= htons(port);
         //ip地址;
         addr.sin_addr.S_un.S_addr= INADDR_ANY;
 
         //绑定地址和协议:
         intret = bind(sock, (struct sockaddr *)&addr, sizeof(addr));
         //绑定失败就返回;
         if(ret != 0)
         {
                   //关闭
                   closesocket(sock);
                   returnfalse;
         }
         //系统的监听函数,决定最多监听多少个人的;
         listen(sock,10);
 
         //这个位置用accpet的话会阻塞,所以开个线程来干;
         //服务端等于这个监听接口;
         _server= sock;
         //在线程启动之前,让判断为0;
         _isConnected= 0;
 
         //写线程执行;第三个参数为线程执行的函数;
         HANDLEhThread = CreateThread(NULL, 0, AcceptThreadFunc, NULL, 0, NULL);
         //执行完后关闭线程;
         CloseHandle(hThread);
 
         returntrue;
}
 
//服务器端线程的函数;
DWORD Net::AcceptThreadFunc(void *)
{
         //链接服务器;就这个是最重要的;
         _connect= accept(_server, NULL, NULL);
 
         //设为1 表示线程启动;
         _isConnected= 1;
 
         //DWORD类型返回的是无符号长整型:unsignedlong int;
         return0;
}
//是否处于已连接状态;
bool Net::isConnected()
{
         return(bool)_isConnected;
}
 
//客户端一边的连接函数;
bool Net::Connect(const char * ip, shortport)
{
         //客户端连接服务器;
         _connect= socket(AF_INET, SOCK_STREAM, 0);
 
         if(_connect == INVALID_SOCKET)
         {
                   returnfalse;
         }
 
         //要求连接的话需要些地址,ip地址结构体:
         structsockaddr_in addr;
         addr.sin_family= AF_INET;
         addr.sin_port= htons(port);
         addr.sin_addr.S_un.S_addr= inet_addr(ip);//<-写地址的方式传入;
 
         //有地址的话就可以连接了:
         intret = connect(_connect, (struct sockaddr *)&addr, sizeof(addr));
         //错误判断;
         if(ret != 0)
         {
                   closesocket(_connect);
                   returnfalse;
         }
         //连接成功,游戏就开始了;不过这里专门处理连接,就不在这里写了;
 
 
         returntrue;
}
 
bool Net::RecvStart()
{
         //这里调用recvStart会阻塞,所以要用线程,实际接收都是在线程里的:
         _isRecvComplete= 0;//为0则可以接收;
         //创建线程,线程里执行完后就关闭线程;
         HANDLEhThread = CreateThread(NULL, 0, RecvThreadFunc, NULL, 0, NULL);
         CloseHandle(hThread);
         returntrue;     
}
 
DWORD Net::RecvThreadFunc(void * arg)
{
         staticchar buf[16];
         //系统函数,sock,接收数据buf,接收长度,链接超时;
         recv(_connect,buf, 16, 0);
         _recvData= buf;//接收数据等于buf;
         _isRecvComplete= 1;//接收成功后等于1,停止接收;
 
         return0;
}
//是否已经接收成功;
bool Net::isRecvComplete()
{
         return(bool)_isRecvComplete;
}
 
//获取数据,len没用,多比少好;
char * Net::RecvData(int &len)
{
         len= 0;//len没用;
         //报文取走,那么报文就要回到没有用的状态;
 
         _isRecvComplete= 0;
 
         return_recvData;
}
 
 
//向客户端发送数据;
int Net::Send(const char * buffer, int len)
{
         returnsend(_connect, buffer, len, 0);
}
 

.h:

#ifndef __Net_H__
#define __Net_H__
 
#include "cocos2d.h"
//如果是windows下的话要写这个;
#ifdef WIN32
#include <WinSock2.h>
#else
//linux
#endif
 
//网络接口;
#include "cocos2d.h"
USING_NS_CC;
class Net
{
public:
         //1.定义socket;要是静态的;
         staticSOCKET _server;//服务器;
         staticSOCKET _connect;//客户端连接服务器;
 
         //传一个变量表示连接状态:
         staticint _isConnected;
         staticint _isRecvComplete;
 
         //传数据;
         staticchar * _recvData;
 
         //监听函数接口:
         staticbool Listen(short port = 9999);
 
         //是否已连接状态;
         staticbool isConnected();
 
         //客户端去连接:
         staticbool Connect(const char * ip, short port = 9999);
 
         //发送数据:
         staticint Send(const char * buffer, int len);
 
         //接收数据:
         staticbool RecvStart();
 
         //是否已经成功接收数据:
         staticbool isRecvComplete();
 
         //告诉接收有多长:
         staticchar * RecvData(int & len);
 
         //接收不是对外的接口:
         staticbool Accept();
 
         //线程调用函数:WINAPI表示一个特殊的接口,是win32的东西,返回类型是DWORD无符号长整型;
         staticDWORD WINAPI AcceptThreadFunc(void * arg);
         staticDWORD WINAPI RecvThreadFunc(void * arg);
};
#endif


 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值