作为菜鸟的我总是希望自己有朝一日 成为高手,于是, 我疯狂的学啊 学啊,
越学越是觉得 自己所掌握的知识 不够,越学 越是 觉得 走不到路得尽头!!!

我热爱编程,为编程而疯狂, 我甚至想 放弃 读书, 在家自学编程。

在网上游荡了这么久, 已经 知道看雪论坛 高手如云, 因此 想进来 和大家技术讨论,

学过 c/c++ ,但是 对 加密解密 这方面 以前没接触过, 但是 对这个非常感兴趣, 

由于 这个对 汇编 要求比较高, 于是 我开始了 汇编的学习之旅 ,学了大概一个多月, 发现 学加密解密 要懂很多知识 才行, 

怕自己 走很多 弯路 ,所以 现在 投奔 看雪 ,希望 能得到 各大高手 指点,

我看这个版块的 说明 要发布 原创文章/程序或解答问题,

发布文章  和 解答问题   (现在可能 没这个能力,毕竟是在看雪,都是厉害人物)

发一些 原创程序 的能力还是有的。

//------------------------------------------------------------------唉 等了好久 都没发邀请码 ,我看了下别人得到邀请码的 帖子, 发现了一个很重要的 问题, 就是  基本上都是 破解贴。 虽然是 破解贴 他们都把 过程很详细的 写出来了。
得到这个启发后 我想重新 来过,   把 整个 过程 写出来。


首先做聊天器,必须了解 TCP/IP 协议,了解 多线程, 了解 和网络编程有关的 API函数

我这里采用的 是 TCP 协议, 首先介绍下 这些函数, 虽然 MSDN里面有详细的 介绍。


int WSAStartup(
  WORD wVersionRequested,
  LPWSADATA lpWSAData
);


作用:WSAStartup函数的使用Ws2_32.dll启动的一个进程。

参数说明:

wVersionRequested -----最高版本的Windows套接字支持 来电可以使用。高阶字节指定的次要版本号(修订本)号码;低字节指定了主版本号。

lpWSAData ------指向 用来接收信息的 WSADATA结构

Example
下面的代码片段演示了如何应用程序仅支持2.2版的Windows套接字使调用WSAStartup:


//---------------------------------------------------这个就是个模板了 ,以后只要用到
//WSAStartup  就用下面 这几句代码 进行初始化

WORD wVersionRequested;
WSADATA wsaData;
int err;

wVersionRequested = MAKEWORD( 2, 2 );

err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 ) {
    return;
}

if ( LOBYTE( wsaData.wVersion ) != 2 ||
        HIBYTE( wsaData.wVersion ) != 2 ) {
    WSACleanup( );
    return; 
}



//----------------------说明

  Windows NT/2000/XP: Included in Windows NT 3.1 and later.
  Windows 95/98/Me: Included in Windows 95 and later.
  Header: Declared in Winsock2.h.
  Library: Use Ws2_32.lib.



----------------------------------------------------------------------
WORD MAKEWORD(
  BYTE bLow, 
  BYTE bHigh 
);

作用:使用socket创建套接字之后再使用这个 宏

参数说明:
bLow ----指定低字节的新值。

bHigh ---指定高字节的新值。


  Windows NT/2000/XP: Included in Windows NT 3.1 and later.
  Windows 95/98/Me: Included in Windows 95 and later.
  Header: Declared in Windef.h; include Windows.h.


----------------------------------------------------------------------------------------

SOCKET socket(
  int af,       
  int type,     
  int protocol  
);

作用:创建套接字

参数说明:
af   ----地址家族,  它只能是 AF_INET  

type ----socket类型   两种 SOCK_STREAM (TCP)       SOCK_DGRAM( UDP)

protocol ----与特定的地址家族相关的协议,如果指定为0,那么他就会根据地质格式和套接字类别自动为您选择合适的协议。


如果说这个函数调用成功,他将返回一个新的SOCKET数据类型的套接字描述符。如果调用失败,这个函数就会返回一个INVALID_SOCKET,错误信息可以通过WSAGetLastError函数返回。

定义 socket的时候 应该这么定义

SOCKET sock=socket(AF_INET,SOCK_STREAM,0);  ---TCP

SOCKET sock=socket(AF_INET,SOCK_DGRAM,0);   ---UDP

  Windows NT/2000/XP: Included in Windows NT 3.1 and later.

  Windows 95/98/Me: Included in Windows 95 and later.

  Header: Declared in Winsock2.h.

  Library: Use Ws2_32.lib.


-----------------------------------------------------------------------------------------
struct sockaddr {
  u_short    sa_family;
  char       sa_data[14];
};   


参数说明:

sa_family -----指定该地址家族,在这里必须设为AF_INET.

sa_data ------仅仅是表示要求一块内存分配区,起到站位的作用,该区域中指定域协议相关的具体信息地址。


//---------------------------------------------------------------------------------------
similar  structure:

struct sockaddr_in {
        short   sin_family;
        u_short sin_port;
        struct  in_addr sin_addr;
        char    sin_zero[8];
};

参数说明:

sin_family ------表示地址族,对于IP地址,它一直是AF_INET

sin_port ----指定的是将要分配给套接字的端口

sin_addr ----给出的是套接字的主机IP地址

sin_zero ----它是一个填充数以使sockaddr_in结构和sockaddr结构的长度一样

如果这个函数调用成功将返回0.如果调用失败,这个函数返回SOCKET_ERROR.

在TCP/IP中,我们可以使用sockaddr_in 结构替换sockaddr,以方便我们填写地址信息

/////////////////////////

一般我们使用 sockaddr_in 这个结构


-------------------------------------------------------------------------------------

int closesocket(
  SOCKET s  
);

关闭一个已存在的socket

参数说明:

s -----已存在的socket 

-------------------------------------------------------------------------------------
unsigned long inet_addr(
  const char   FAR *cp  
);

作用:该函数将一个字符窜型的 IPV4英特网协议带点的地址 转换成 IN_ADDR结构的合适地址 

参数说明:

cp ------ 带点的字符串型的 IPv4英特网协议带点地址

example:

inet_addr("127.0.0.1")



  Windows NT/2000/XP: Included in Windows NT 3.1 and later.
  Windows 95/98/Me: Included in Windows 95 and later.
  Header: Declared in Winsock2.h.
  Library: Use Ws2_32.lib.

------------------------------------------------------------------------------------


int  WSACleanup (void);

释放socket 

example:

    WSACleanup();

int bind(
  SOCKET s,                          
  const struct sockaddr FAR *name,   
  int namelen                        
);

作用:  将本地地址和socket绑定

参数说明:

s  ----没绑定的套接字

name  ----地址从SOCKADD结构中分配给socket

namelen ----name变量的长度


example:
   
bind(sockServer,(sockaddr*)&addrServer,sizeof(sockaddr));



  Windows NT/2000/XP: Included in Windows NT 3.1 and later.
  Windows 95/98/Me: Included in Windows 95 and later.
  Header: Declared in Winsock2.h.
  Library: Use Ws2_32.lib.

----------------------------------------------------------------------------------------------

int listen(
  SOCKET s,    
  int backlog  
);

参数说明:
s  -----已经bind得socket

backlog -----允许连接客服端的最大值

example:

    listen(sockServer,10);


  Windows NT/2000/XP: Included in Windows NT 3.1 and later.
  Windows 95/98/Me: Included in Windows 95 and later.
  Header: Declared in Winsock2.h.
  Library: Use Ws2_32.lib.


---------------------------------------------------------------------------------------------

SOCKET accept(
  SOCKET s,
  struct sockaddr FAR *addr,
  int FAR *addrlen
);

作用:accept 函数允许一个尝试连接到socket

参数说明:

s ----- 一个处于listen状态的套接字

addr ----指向 以创建的sockaddr结构

addrlen ----addr的长度 


example :

SOCKET sockConnection=accept(sock,(sockaddr*)&addrServer,sizeof(sockaddr));


------------------------------------------------------------------------------------------

int connect(
  SOCKET s,                          
  const struct sockaddr FAR *name,  
  int namelen                        
);


作用:该函数用于TCP协议的客服端连接服务端

参数说明:

s -----一个没有被连接的socket

name -----server的 sockaddr_in结构

namelen ----- sizeof(sockaddr)

example:

     connect(sockClient,(sockaddr*)&addrServer,sizeof(sockaddr));



  Windows NT/2000/XP: Included in Windows NT 3.1 and later.
  Windows 95/98/Me: Included in Windows 95 and later.
  Header: Declared in Winsock2.h.
  Library: Use Ws2_32.lib.

---------------------------------------------------------------------------------------------

int recv(
  SOCKET s,       
  char FAR *buf,  
  int len,        
  int flags       
);

作用: 该函数用来接收数据

参数说明:

s   ----一个socket结构,该socket必须是已经连接的

buf ------接收到信息后,将信息存放放到buf里面

len ------buf 的长度

flags ----一般 设置为0


example:

recv(sockConnection,cGetInfo,strlen(cGetInfo)+1,0);


  Windows NT/2000/XP: Included in Windows NT 3.1 and later.
  Windows 95/98/Me: Included in Windows 95 and later.
  Header: Declared in Winsock2.h.
  Library: Use Ws2_32.lib.


---------------------------------------------------------------------------------------------

int send(
  SOCKET s,              
  const char FAR *buf,  
  int len,               
  int flags              
);

作用:该函数用来发送信息

参数说明:

s ----- 已经处于连接状态的socket

buf -----发送信息的内容存放在 buf里面

len   -----buf 的长度

flags -----一般设置为 0


example :

send(sockConnection,cSendInfo,strlen(cSendInfo)+1,0);


  Windows NT/2000/XP: Included in Windows NT 3.1 and later.
  Windows 95/98/Me: Included in Windows 95 and later.
  Header: Declared in Winsock2.h.
  Library: Use Ws2_32.lib.




-------------------------------------------------------

和TCP 编程 相关的 函数 
recv 接收数据,客户端 和服务端 必须用这个 函数
send 发送信息 ,客服端和服务端 必须用这个函数
connect  连接, 就是客户端连接服务端 ,所以 只有 客户端用这个函数
accept    接收  ,就是 服务端 允许或接受客户端的请求,所以 只有服务端使用这个函数
bind  绑定,服务端对socket进行绑定 ,只有服务端使用这个函数
listen  监听,服务端对已绑定的socket进行监听,这样才能使用socket进行通信,所以,只有服务端使用这个函数

---------------------------------------------以上是 和 网络编程相关的 api函数, 下面介绍 和多线有关的函数。

HANDLE CreateThread(
  LPSECURITY_ATTRIBUTES lpThreadAttributes, // SD
  SIZE_T dwStackSize,                       // initial stack size
  LPTHREAD_START_ROUTINE lpStartAddress,    // thread function
  LPVOID lpParameter,                       // thread argument
  DWORD dwCreationFlags,                    // creation option
  LPDWORD lpThreadId                        // thread identifier
);

这个函数是创建线程的函数  API函数
来看看这个函数的参数
lpThreadAttributes --------- 安全属性,  一般这个参数可以 设置为NULL
dwStackSize ---------- 初始化 堆区大小 , 一般这个参数 设置为0
lpStartAddress ------- 线程函数的初始地址 ,参数 就是你 写的线程函数 的函数名
lpParameter ----------为线程函数 传递的值
dwCreationFlags ---------一般设置为0
lpThreadId ----------一般设置 为 NULL

  Windows NT/2000/XP: Included in Windows NT 3.1 and later.
  Windows 95/98/Me: Included in Windows 95 and later.
  Header: Declared in Winbase.h; include Windows.h.
  Library: Use Kernel32.lib.


---------------------------------------------------------关于 lpStartAddress 这个线程初始函数


DWORD WINAPI ThreadProc(
  LPVOID lpParameter   // thread data
);

关于 这个线程 函数名 是可以修改的  也就是  ThreadProc 是可以修改的 

example 

DWORD WINAPI newthread(LPVOID lpParameter);


//----------------------------------------------------------------------------

整个 通信过程, 大家 可以看以下图片。





//-----------------------------------------限于篇幅原因,在下一个贴里面继续讲解
//-----------------------------------------由于第一次发帖时, client.rar里面的源代码有点问题,我下面的贴中补充了。

上传的附件 tcp_server2.rar