实验一:基于Winsock完成简单的网络程序开发

2023-07-10

第一部分:简答的UDP网络通信程序

 // UDP5555.cpp : Defines the entry point for the application.
//=========================================================================
//陈家琪,计算机网络课程,传输层与应用层协议-用户数据报协议UDP
//说明:在窗口里点击鼠标左键,则发送信息到远程机。
//=========================================================================
//VC 6.0 add WSOCK32.LIB in Project -> Settings... -> Link
#include <winsock.h>
//--------------------------------------------------------------
// Global Variables:
HINSTANCE hInst; // 实例句柄,方便各程序访问
HWND hWnd; // 主窗口句柄,方便各程序访问
char Title[]="UDP[5555]"; // 窗口标题 The title bar text
int WinX0=,WinY0=,WinW=,WinH=; // 窗口位置、大小 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//--------------------------------------------------------------
int APIENTRY WinMain(HINSTANCE hI,HINSTANCE hP,LPSTR lp,int nC)
{
MSG msg;
hInst = hI; // Store instance handle in our global variable
WNDCLASS wc; memset(&wc,,sizeof(WNDCLASS)); wc.lpfnWndProc = (WNDPROC)WndProc;
wc.hInstance = hI;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE+);
wc.lpszClassName = "Win32API";
RegisterClass(&wc);
//特殊窗口1,始终在顶层,任务栏显示。
hWnd=CreateWindowEx(WS_EX_TOPMOST,"Win32API",Title,
WS_DLGFRAME|WS_SYSMENU,
WinX0,WinY0,WinW,WinH, // 窗口位置、大小
NULL, NULL, hI, NULL); if (!hWnd) return FALSE; ShowWindow(hWnd, nC);
// Main message loop:
while (GetMessage(&msg, NULL, , ))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
//--------------------------------------------------------------
WSADATA ws;
SOCKET Cs1,Cs2;
struct sockaddr_in Cs1A,Cs2A;
char aa[];
char bb[];
int d;
#define Cs1Port 5555 //本地端口
#define Cs2Port 6666 //远程端口
#define Cs1IP "127.0.0.1" //本地网址
#define Cs2IP "127.0.0.1" //远程网址
//--------------------------------------------------------------
//消息处理
LRESULT CALLBACK WndProc(HWND hW, UINT msg, WPARAM wP, LPARAM lP)
{
switch (msg)
{
case WM_DESTROY: //关闭程序触发事件
WSAAsyncSelect(Cs1, hW, , ); //向Windows注销Socket触发事件
closesocket(Cs1); //释放连接
WSACleanup( ); //卸载动态连接库WinSock DLL
PostQuitMessage();
break;
case WM_CREATE: //程序初始化触发事件
WSAStartup(0x0101,&ws); //装载动态连接库WinSock DLL
Cs1=socket(AF_INET, SOCK_DGRAM,); //创建UDP套接字Socket
Cs1A.sin_family=AF_INET; //地址类型:AF_INET for Internet
Cs1A.sin_port = htons(Cs1Port); //本地Socket的属性:端口
Cs1A.sin_addr.s_addr =inet_addr(Cs1IP); //本地Socket的属性:IP地址
d=bind(Cs1,(struct sockaddr *) &Cs1A,sizeof(Cs1A)); //设置本地socket的属性,捆绑
Cs2A.sin_family=AF_INET; //地址类型:AF_INET for Internet
Cs2A.sin_port = htons(Cs2Port); //远程Socket的属性:端口
Cs2A.sin_addr.s_addr =inet_addr(Cs2IP); //远程Socket的属性:IP地址
WSAAsyncSelect(Cs1,hW,WM_USER+,FD_READ); //向Windows注册Socket触发事件
Beep(,);
break;
case WM_USER+: //Socket触发事件
switch(LOWORD(lP))
{
case FD_READ: //收到远程信息
// d=recvfrom(Cs1,bb,sizeof(bb),0,(struct sockaddr *) &Cs2A,&d);
d=recv(wP,bb,sizeof(bb),);//wP=Cs //读接收缓冲区
bb[d]=;
MessageBox(,bb,"UDP[5555](FD_READ)",);
break;
}
break;
case WM_LBUTTONDOWN: //点击鼠标左键
wsprintf(aa,"UDP[5555]:Hello!");
d = sizeof(Cs2A);
sendto(Cs1,aa,strlen(aa),,(struct sockaddr *) &Cs2A,d); //发送信息"UDP[5555]:Hello!"
break;
}
return DefWindowProc(hW,msg,wP,lP);
}
//--------------------------------------------------------------

UDP5555.cpp

 // UDP6666.cpp : Defines the entry point for the application.
//=========================================================================
//用户数据报协议UDP
//说明:在窗口里点击鼠标左键,则发送信息到远程机。
//=========================================================================
//VC 6.0 add WSOCK32.LIB in Project -> Settings... -> Link
#include <winsock.h>
//--------------------------------------------------------------
// Global Variables:
HINSTANCE hInst; // 实例句柄,方便各程序访问
HWND hWnd; // 主窗口句柄,方便各程序访问
char Title[]="UDP[6666]"; // 窗口标题 The title bar text
int WinX0=,WinY0=,WinW=,WinH=; // 窗口位置、大小 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//--------------------------------------------------------------
int APIENTRY WinMain(HINSTANCE hI,HINSTANCE hP,LPSTR lp,int nC)
{
MSG msg;
hInst = hI; // Store instance handle in our global variable
WNDCLASS wc; memset(&wc,,sizeof(WNDCLASS)); wc.lpfnWndProc = (WNDPROC)WndProc;
wc.hInstance = hI;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE+);
wc.lpszClassName = "Win32API";
RegisterClass(&wc);
//特殊窗口1,始终在顶层,任务栏显示。
hWnd=CreateWindowEx(WS_EX_TOPMOST,"Win32API",Title,
WS_DLGFRAME|WS_SYSMENU,
WinX0,WinY0,WinW,WinH, // 窗口位置、大小
NULL, NULL, hI, NULL); if (!hWnd) return FALSE; ShowWindow(hWnd, nC);
// Main message loop:
while (GetMessage(&msg, NULL, , ))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
//--------------------------------------------------------------
WSADATA ws;
SOCKET Cs1,Cs2;
struct sockaddr_in Cs1A,Cs2A;
char aa[];
char bb[];
int d;
#define Cs1Port 6666 //本地端口
#define Cs2Port 5555 //远程端口
#define Cs1IP "127.0.0.1" //本地网址
#define Cs2IP "127.0.0.1" //远程网址
//--------------------------------------------------------------
//消息处理
LRESULT CALLBACK WndProc(HWND hW, UINT msg, WPARAM wP, LPARAM lP)
{
switch (msg)
{
case WM_DESTROY: //关闭程序触发事件
WSAAsyncSelect(Cs1, hW, , ); //向Windows注销Socket触发事件
closesocket(Cs1); //释放连接
WSACleanup( ); //卸载动态连接库WinSock DLL
PostQuitMessage();
break;
case WM_CREATE: //程序初始化触发事件
WSAStartup(0x0101,&ws); //装载动态连接库WinSock DLL
Cs1=socket(AF_INET, SOCK_DGRAM,); //创建UDP套接字Socket
Cs1A.sin_family=AF_INET; //地址类型:AF_INET for Internet
Cs1A.sin_port = htons(Cs1Port); //本地Socket的属性:端口
Cs1A.sin_addr.s_addr =inet_addr(Cs1IP); //本地Socket的属性:IP地址
d=bind(Cs1,(struct sockaddr *) &Cs1A,sizeof(Cs1A)); //设置本地socket的属性,捆绑
Cs2A.sin_family=AF_INET; //地址类型:AF_INET for Internet
Cs2A.sin_port = htons(Cs2Port); //远程Socket的属性:端口
Cs2A.sin_addr.s_addr =inet_addr(Cs2IP); //远程Socket的属性:IP地址
WSAAsyncSelect(Cs1,hW,WM_USER+,FD_READ); //向Windows注册Socket触发事件
Beep(,);
break;
case WM_USER+: //Socket触发事件
switch(LOWORD(lP))
{
case FD_READ: //收到远程信息
// d=recvfrom(Cs1,bb,sizeof(bb),0,(struct sockaddr *) &Cs2A,&d);
d=recv(wP,bb,sizeof(bb),);//wP=Cs //读接收缓冲区
bb[d]=;
MessageBox(,bb,"UDP[6666](FD_READ)",);
break;
}
break;
case WM_LBUTTONDOWN: //点击鼠标左键
wsprintf(aa,"UDP[6666]:Hello!");
d = sizeof(Cs2A);
sendto(Cs1,aa,strlen(aa),,(struct sockaddr *) &Cs2A,d); //发送信息"UDP[6666]:Hello!"
break;
}
return DefWindowProc(hW,msg,wP,lP);
}
//--------------------------------------------------------------

UDP6666.cpp

第二部分:简单的TCP网络通信程序

 //Server.cpp : Defines the entry point for the application. use VC 6.0
//=========================================================================
//说明:监听客户机连接请求, 向客户机发送连接应答"Server:Welcome!";
//说明:接收客户机服务请求, 向客户机发送服务数据.
//=========================================================================
//VC6.0 add WSOCK32.LIB in Project->Settings...->Link
#include <winsock.h> //by user
//------------------------------------------------
// Global Variables:
HINSTANCE hInst; // 实例句柄,方便各程序访问
HWND hWnd; // 主窗口句柄,方便各程序访问
char Title[]=" TCP-Server "; // 窗口标题 The title bar text
int WinX0=,WinY0=,WinW=,WinH=; // 窗口位置、大小 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//------------------------------------------------
int APIENTRY WinMain(HINSTANCE hI,HINSTANCE hP,LPSTR lp,int nC)
{
MSG msg;
hInst = hI; // Store instance handle in our global variable
WNDCLASS wc; memset(&wc,,sizeof(WNDCLASS)); wc.lpfnWndProc = (WNDPROC)WndProc;
wc.hInstance = hI;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE+);
wc.lpszClassName = "Win32API";
RegisterClass(&wc);
//特殊窗口1,始终在顶层,任务栏显示。
hWnd=CreateWindowEx(WS_EX_TOPMOST,"Win32API",Title,
WS_DLGFRAME|WS_SYSMENU,
WinX0,WinY0,WinW,WinH, // 窗口位置、大小
NULL, NULL, hI, NULL);
if(!hWnd) return FALSE; ShowWindow(hWnd, nC);
// Main message loop:
while (GetMessage(&msg, NULL, , ))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
//------------------------------------------------
WSADATA ws;
SOCKET Ss,Cs; //服务器和客户机的套接口变量
struct sockaddr_in SA,CA; //服务器和客户机的主机地址变量
WORD SPort = ; //本机端口(服务器)
//char SIP[16]="127.0.0.1"; //本机IP地址(服务器)
char SIP[]="0.0.0.0"; //本机IP地址(服务器)
char Msg[],Buf[];
int d,l=sizeof(CA);
//------------------------------------------------
void SetSockAddr(struct sockaddr_in *A,WORD Port,char *IP)
{
A->sin_family = AF_INET; //TCP/IP协议
A->sin_port = htons(Port); //端口。
A->sin_addr.s_addr =inet_addr(IP); //IP网址。
}
//------------------------------------------------
//消息处理
LRESULT CALLBACK WndProc(HWND hW,UINT msg,
WPARAM wP,LPARAM lP)
{
switch (msg)
{
case WM_CREATE: //消息:产生窗口
WSAStartup(0x0101,&ws);
Ss=socket(AF_INET, SOCK_STREAM,); //创建套接口(流式)
SetSockAddr(&SA,SPort,SIP); //设置服务器主机地址
d=bind(Ss,(struct sockaddr *)&SA,sizeof(SA));//捆绑主机地址
if(d!=)
{
wsprintf(Msg,"[Server] %s","bind Error!");
SetWindowText(hW, Msg); //在窗口标题栏显示连接信息
break;
}
//向windows注册套接口Ss所产生的网络消息事件。
WSAAsyncSelect(Ss,hW,WM_USER+,FD_ACCEPT|FD_READ|FD_CLOSE);
listen(Ss,); //监听客户机连接请求
break;
case WM_DESTROY: //消息:关闭窗口
WSAAsyncSelect(Ss, hW, , ); //注销套接口Ss的消息事件。
closesocket(Ss); //关闭套接口Ss
WSACleanup(); //卸载WinSock DLL
PostQuitMessage(); //向windows发送退出程序的消息
break;
case WM_USER+:
switch(LOWORD(lP))
{
case FD_ACCEPT:
Cs=accept(Ss,(struct sockaddr *)&CA,&l);//获取客户机主机地址
wsprintf(Msg,"[Server]Client[%d] come in!",Cs);
SetWindowText(hW, Msg); //在窗口标题栏显示连接信息 wsprintf(Msg,"Server:Welcome!");
send(Cs, Msg,strlen(Msg),); //向客户机发送连接应答
break;
case FD_READ:
d=recv(wP,Buf,sizeof(Buf),); //接收客户机服务请求,wP=Cs
Buf[d]=;
wsprintf(Msg,"[Server]Client[%d]:%s",wP,Buf);
SetWindowText(hW, Msg); //在窗口标题栏显示服务请求 wsprintf(Msg,"Server:%s",Buf);
send(wP, Msg,strlen(Msg),); //向客户机发送服务数据
break;
case FD_CLOSE:
wsprintf(Msg,"[Server]Client[%d] leave!",wP);
SetWindowText(hW, Msg); //在窗口标题栏显示信息
break;
}
break;
}
return DefWindowProc(hW,msg,wP,lP);
}
//------------------------------------------------

server.cpp

 //Client.cpp : Defines the entry point for the application. use VC 6.0
//=========================================================================
//基于TCP,Client程序
//说明:鼠标左键按下: 向服务器发送服务请求"Hello!"
//说明:鼠标右键按下: 向服务器发送服务请求"Hi!"
//=========================================================================
//VC6.0 add WSOCK32.LIB in Project->Settings...->Link
#include <winsock.h> //by user
//------------------------------------------------
// Global Variables:
HINSTANCE hInst; // 实例句柄,方便各程序访问
HWND hWnd; // 主窗口句柄,方便各程序访问
char Title[]=" TCP-Client "; // 窗口标题 The title bar text
int WinX0=,WinY0=,WinW=,WinH=; // 窗口位置、大小 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//------------------------------------------------
int APIENTRY WinMain(HINSTANCE hI,HINSTANCE hP,LPSTR lp,int nC)
{
MSG msg;
hInst = hI; // Store instance handle in our global variable
WNDCLASS wc; memset(&wc,,sizeof(WNDCLASS)); wc.lpfnWndProc = (WNDPROC)WndProc;
wc.hInstance = hI;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE+);
wc.lpszClassName = "Win32API";
RegisterClass(&wc);
//特殊窗口1,始终在顶层,任务栏显示。
hWnd=CreateWindowEx(WS_EX_TOPMOST,"Win32API",Title,
WS_DLGFRAME|WS_SYSMENU,
// WinX0,WinY0,WinW,WinH, // 窗口位置、大小
CW_USEDEFAULT,CW_USEDEFAULT,WinW,WinH, // 窗口位置 Windows selects the default position 、大小
NULL, NULL, hI, NULL);
if(!hWnd) return FALSE; ShowWindow(hWnd, nC);
// Main message loop:
while (GetMessage(&msg, NULL, , ))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
//------------------------------------------------
WSADATA ws;
SOCKET Ss,Cs; //服务器和客户机的套接口变量
struct sockaddr_in SA,CA; //服务器和客户机的主机地址变量
WORD SPort = ; //远程服务器端口
char SIP[]="127.0.0.1"; //远程服务器IP地址
//char SIP[16]="0.0.0.0"; //远程服务器IP地址
char Msg[],Buf[];
int d,l=sizeof(CA);
//------------------------------------------------
void SetSockAddr(struct sockaddr_in *A,WORD Port,char *IP)
{
A->sin_family = AF_INET; //TCP/IP协议
A->sin_port = htons(Port); //端口。
A->sin_addr.s_addr =inet_addr(IP); //IP网址。
}
//------------------------------------------------
//消息处理
LRESULT CALLBACK WndProc(HWND hW,UINT msg,WPARAM wP,LPARAM lP)
{
switch (msg)
{
case WM_CREATE:
WSAStartup(0x0101,&ws);
Cs=socket(AF_INET,SOCK_STREAM,); //创建套接口(流式)
SetSockAddr(&SA,SPort,SIP); //服务器主机地址(远程)
WSAAsyncSelect(Cs,hW,WM_USER+,FD_READ|FD_CLOSE);
d=connect(Cs,(struct sockaddr *)&SA, sizeof(SA));//连接服务器
if(d!=)
{
wsprintf(Msg,"[Client]%s","connect Error!");
SetWindowText(hW, Msg); //在窗口标题栏显示服务数据
break;
} break;
case WM_DESTROY: //消息:关闭窗口
WSAAsyncSelect(Cs, hW, , ); //注销套接口Cs的消息事件。
closesocket(Cs); //关闭套接口Cs
WSACleanup(); //卸载WinSock DLL
PostQuitMessage(); //向windows发送退出程序的消息
break;
case WM_USER+:
switch(LOWORD(lP))
{
case FD_READ:
d=recv(wP,Buf,sizeof(Buf),); //接收服务器的服务数据,wP=Cs
Buf[d]=;
wsprintf(Msg,"[Client]%s",Buf);
SetWindowText(hW, Msg); //在窗口标题栏显示服务数据
break;
case FD_CLOSE:
wsprintf(Msg,"[Client]Server Stop! [%d]",wP);
SetWindowText(hW, Msg); //在窗口标题栏显示信息
break;
}
break;
case WM_LBUTTONDOWN: //消息:鼠标左键按下
wsprintf(Msg,"Hello!");
send(Cs, Msg,strlen(Msg),); //向服务器发送服务请求"Hello!"
break;
case WM_RBUTTONDOWN: //消息:鼠标右键按下
wsprintf(Msg,"Hi!");
send(Cs, Msg,strlen(Msg),); //向服务器发送服务请求"Hi!"
break;
}
return DefWindowProc(hW,msg,wP,lP);
}
//------------------------------------------------

client.cpp

第三部分:简单的CHAR聊天室网络应用程序

 //ChatSer.cpp : Defines the entry point for the application. use VC 6.0
//=========================================================================
//传输层协议-传输控制协议TCP
//说明: Chat Server服务器端程序
//=========================================================================
//VC 6.0 add WSOCK32.LIB in Project -> Settings... -> Link
#include <winsock.h>
#include <stdlib.h>
//--------------------------------------------------------------
// Global Variables:
HINSTANCE hInst; // 实例句柄,方便各程序访问
HWND hWnd; // 主窗口句柄,方便各程序访问
char Title[]="Chat-Server"; // 窗口标题 The title bar text
int WinX0=,WinY0=,WinW=,WinH=; // 窗口位置、大小 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//--------------------------------------------------------------
int APIENTRY WinMain(HINSTANCE hI,HINSTANCE hP,LPSTR lp,int nC)
{
MSG msg;
hInst = hI; // Store instance handle in our global variable
WNDCLASS wc; memset(&wc,,sizeof(WNDCLASS)); wc.lpfnWndProc = (WNDPROC)WndProc;
wc.hInstance = hI;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE+);
wc.lpszClassName = "Win32API";
RegisterClass(&wc);
//特殊窗口1,始终在顶层,任务栏显示。
hWnd=CreateWindowEx(WS_EX_TOPMOST,"Win32API",Title,
WS_DLGFRAME|WS_SYSMENU,
WinX0,WinY0,WinW,WinH, // 窗口位置、大小
NULL, NULL, hI, NULL);
if(!hWnd) return FALSE; ShowWindow(hWnd, nC);
// Main message loop:
while (GetMessage(&msg, NULL, , ))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
//--------------------------------------------------------------
//按钮
HWND CreateButton(char *Titel,int x0,int y0,int w,int h,int ID,HWND hW,HINSTANCE hInst)
{
return CreateWindowEx(WS_EX_PALETTEWINDOW,"BUTTON",Titel,
WS_VISIBLE | WS_CHILD ,
x0,y0,w,h, hW,(HMENU)ID,hInst,NULL);
}
//---------------------------------------------------------------------------
//单行编辑框
HWND CreateEdit(char *Titel,int x0,int y0,int w,int h,int ID,HWND hW,HINSTANCE hInst)
{
return CreateWindowEx(WS_EX_CLIENTEDGE,"EDIT",Titel,
WS_VISIBLE | WS_CHILD |
ES_LEFT | ES_MULTILINE | WS_HSCROLL ,
x0,y0,w,h, hW,
(HMENU)ID,hInst,NULL);
}
//---------------------------------------------------------------------------
//多行文本框
HWND CreateMemo(char *Titel,int x0,int y0,int w,int h,int ID,HWND hW,HINSTANCE hInst)
{
return CreateWindowEx(WS_EX_CLIENTEDGE,"EDIT",Titel,
WS_VISIBLE | WS_CHILD |
ES_LEFT | ES_MULTILINE |ES_READONLY|
WS_HSCROLL | WS_VSCROLL,
x0,y0,w,h,
hW,(HMENU)ID,hInst,NULL);
}
//---------------------------------------------------------------------------
//向多行文本框中添加文本
void Puts(HWND hW,int ID_EDIT,char *str)
{
int nLen=GetWindowTextLength(GetDlgItem(hW,ID_EDIT));
SendMessage(GetDlgItem(hW,ID_EDIT),EM_SETSEL,nLen,nLen);
SendMessage(GetDlgItem(hW,ID_EDIT),EM_REPLACESEL,TRUE,(long)(LPCTSTR)str);
nLen=GetWindowTextLength(GetDlgItem(hW,ID_EDIT));
SendMessage(GetDlgItem(hW,ID_EDIT),EM_SETSEL,nLen,nLen);
SendMessage(GetDlgItem(hW,ID_EDIT),EM_REPLACESEL,TRUE,(long)(LPCTSTR)"\r\n");
}
//---------------------------------------------------------------------------
//按钮
#define BUTTON1 501
#define BUTTON2 502
//---------------------------------------------------------------------------
//单行编辑框
#define EDIT1 601
#define EDIT2 602
#define EDIT3 603
//---------------------------------------------------------------------------
//多行编辑框
#define MEMO1 701
//---------------------------------------------------------------------------
#define UN 100 //100个用户登录信息
WSADATA ws;
SOCKET Ss,Cs,Csi[UN];
struct sockaddr_in SA,CA,CAi[];
char aa[];
char bb[];
char User[UN][];
int d;
int GetUserBySocket(SOCKET s)
{
int i;
for(i=;i<UN;i++)
if(Csi[i]==s)
break;
return i;
}
void Broadcast(SOCKET s,char *str)
{
char a1[];
int i;
int ui;
ui = GetUserBySocket(s);
for(i=;i<UN;i++)
{
if(Csi[i]==-) continue;
wsprintf(a1,"%s:%s",User[ui],str);
send(Csi[i],a1,strlen(a1),);
}
}
int NameCmp(char *str)
{
int i;
for(i=;i<UN;i++)
if(!strcmp(User[i],str)) return ;
return ;
}
void BroadcastToClients(HWND hW,SOCKET s,char *str) //向其它客户转发信息或用户登录名注册
{
int i,j=;
for(i=;i<UN;i++)
if((Csi[i]==s) && (User[i][]==))
{
strcpy(aa,str);
while(NameCmp(aa)) //查找用户登录名
wsprintf(aa,"%s-%d",str,j++);
if(j>)
{
wsprintf(bb,"Your Name=%s!",aa);
send(s,bb,strlen(bb),);
}
strcpy(User[i],aa);
wsprintf(aa,"Come in!");
Broadcast(s,aa); //广播“新用户 Come in!”
wsprintf(aa,"%s:Come in![%s:%d]",User[i],
inet_ntoa(CAi[i].sin_addr),ntohs(CAi[i].sin_port));
Puts(hW,MEMO1,aa);
return;
}
Broadcast(s,str); //广播客户发来信息
}
void DelUserName(HWND hW,SOCKET s,char *str) //删除释放连接的用户登录信息
{
int i;
int ui;
ui = GetUserBySocket(s);
for(i=;i<UN;i++)
if(Csi[i]==s)
{
Broadcast(s,str);
wsprintf(aa,"%s:%s[%s:%d]",User[ui],str,
inet_ntoa(CAi[i].sin_addr),ntohs(CAi[i].sin_port));
Puts(hW,MEMO1,aa);
Csi[i]=-;
User[i][]=;
return;
}
}
void AddUser() //添加建立连接的用户登录信息
{
int i;
for(i=;i<UN;i++)
if(Csi[i]==-)
{
Csi[i]=Cs;
CAi[i]=CA;
User[i][]=;
break;
}
}
//---------------------------------------------------------------------------
//消息处理
LRESULT CALLBACK WndProc(HWND hW, UINT msg, WPARAM wP, LPARAM lP)
{
int i;
switch (msg)
{
case WM_DESTROY: //关闭程序触发事件
WSAAsyncSelect(Ss, hW, , ); //向Windows注销Socket触发事件
closesocket(Ss); //释放连接
WSACleanup( ); //卸载动态连接库WinSock DLL
PostQuitMessage();
break;
case WM_CREATE: //程序初始化触发事件
WSAStartup(0x0101,&ws); //装载动态连接库WinSock DLL
CreateButton("Send",,,,,BUTTON1,hW,hInst); //Chat Server的推送信息按钮
CreateButton("Start",,,,,BUTTON2,hW,hInst); //启动服务按钮
CreateEdit("127.0.0.1",,,,,EDIT2,hW,hInst); //Chat Server的IP地址输入框
CreateEdit("",,,,,EDIT3,hW,hInst); //Chat Server的Port端口输入框
CreateEdit("Hello!",,,,,EDIT1,hW,hInst); //Chat Server的推送信息输入框
CreateMemo("Info.", ,,,,MEMO1,hW,hInst); //客户登录信息显示窗口
SetFocus(GetDlgItem(hW,BUTTON1));
EnableWindow(GetDlgItem(hW,BUTTON1),FALSE);
EnableWindow(GetDlgItem(hW,BUTTON2),TRUE);
for(i=;i<UN;i++) //初始化客户登录信息变量
{
Csi[i]=-;
User[i][]=;
}
break;
case WM_USER+: //Socket触发事件
switch(LOWORD(lP))
{
case FD_ACCEPT: //Chat Client的建立连接请求
d=sizeof(CA);
Cs=accept(Ss,(struct sockaddr *) &CA,&d); //接受Chat Client的连接请求
AddUser(); //添加建立连接的用户登录信息
break;
case FD_READ: //收到Chat Client信息
d=recv(wP,bb,sizeof(bb),);//wP=Cs //读接收缓冲区 bb[d]=;
BroadcastToClients(hW,wP,bb); //向其它客户转发信息或用户登录名注册
break;
case FD_CLOSE: //Chat Client的释放连接请求
wsprintf(bb,"Leave!");
DelUserName(hW,wP,bb); //删除释放连接的用户登录信息
break;
}
break;
case WM_COMMAND: //控件触发事件
switch(wP)
{
case BUTTON1: //按下推送信息按钮
GetDlgItemText(hW,EDIT1,bb,sizeof(bb));
for(i=;i<UN;i++) //向登录的客户推送信息
{
if(Csi[i]==-) continue;
wsprintf(aa,"Server:%s",bb);
send(Csi[i],aa,strlen(aa),);
}
break;
case BUTTON2: //按下启动服务按钮
EnableWindow(GetDlgItem(hW,BUTTON2),FALSE);
EnableWindow(GetDlgItem(hW,BUTTON1),TRUE);
EnableWindow(GetDlgItem(hW,EDIT2),FALSE);
EnableWindow(GetDlgItem(hW,EDIT3),FALSE);
GetDlgItemText(hW,EDIT2,aa,sizeof(aa));
GetDlgItemText(hW,EDIT3,bb,sizeof(bb));
Ss=socket(AF_INET, SOCK_STREAM,); //创建TCP套接字Socket
SA.sin_family=AF_INET; //Chat Server的属性:地址类型 AF_INET for Internet
SA.sin_port = htons(atoi(bb)); //Chat Server的属性:端口
SA.sin_addr.s_addr =inet_addr(aa); //Chat Server的属性:IP地址 bind(Ss,(struct sockaddr *) &SA,sizeof(SA)); //设置socket属性
WSAAsyncSelect(Ss,hW,WM_USER+,FD_ACCEPT|FD_READ|FD_CLOSE); //向Windows注册Socket触发事件
listen(Ss,); //建立连接缓冲区,100个连接
Beep(,);
break;
}
break;
}
return DefWindowProc(hW,msg,wP,lP);
}
//--------------------------------------------------------------

charser.cpp

 //ChatCli.cpp : Defines the entry point for the application. use VC 6.0
//=========================================================================
//传输控制协议TCP
//说明: Chat Client客户端程序
//=========================================================================
//VC 6.0 add WSOCK32.LIB in Project -> Settings... -> Link
#include <winsock.h>
#include <stdlib.h>
//--------------------------------------------------------------
// Global Variables:
HINSTANCE hInst; // 实例句柄,方便各程序访问
HWND hWnd; // 主窗口句柄,方便各程序访问
char Title[]="Chat-Client"; // 窗口标题 The title bar text
int WinX0=,WinY0=,WinW=,WinH=; // 窗口位置、大小 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//--------------------------------------------------------------
int APIENTRY WinMain(HINSTANCE hI,HINSTANCE hP,LPSTR lp,int nC)
{
MSG msg;
hInst = hI; // Store instance handle in our global variable
WNDCLASS wc; memset(&wc,,sizeof(WNDCLASS)); wc.lpfnWndProc = (WNDPROC)WndProc;
wc.hInstance = hI;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE+);
wc.lpszClassName = "Win32API";
RegisterClass(&wc);
//特殊窗口1,始终在顶层,任务栏显示。
hWnd=CreateWindowEx(WS_EX_TOPMOST,"Win32API",Title,
WS_DLGFRAME|WS_SYSMENU,
// WinX0,WinY0,WinW,WinH, // 窗口位置、大小
CW_USEDEFAULT,CW_USEDEFAULT,WinW,WinH, // 窗口位置 Windows selects the default position 、大小
NULL, NULL, hI, NULL);
if(!hWnd) return FALSE; ShowWindow(hWnd, nC);
// Main message loop:
while (GetMessage(&msg, NULL, , ))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
//--------------------------------------------------------------
//按钮
HWND CreateButton(char *Titel,int x0,int y0,int w,int h,int ID,HWND hW,HINSTANCE hInst)
{
return CreateWindowEx(WS_EX_PALETTEWINDOW,"BUTTON",Titel,
WS_VISIBLE | WS_CHILD ,
x0,y0,w,h, hW,(HMENU)ID,hInst,NULL);
}
//---------------------------------------------------------------------------
//单行编辑框
HWND CreateEdit(char *Titel,int x0,int y0,int w,int h,int ID,HWND hW,HINSTANCE hInst)
{
return CreateWindowEx(WS_EX_CLIENTEDGE,"EDIT",Titel,
WS_VISIBLE | WS_CHILD |
ES_LEFT | ES_MULTILINE | WS_HSCROLL ,
x0,y0,w,h, hW,
(HMENU)ID,hInst,NULL);
}
//---------------------------------------------------------------------------
//多行文本框
HWND CreateMemo(char *Titel,int x0,int y0,int w,int h,int ID,HWND hW,HINSTANCE hInst)
{
return CreateWindowEx(WS_EX_CLIENTEDGE,"EDIT",Titel,
WS_VISIBLE | WS_CHILD |
ES_LEFT | ES_MULTILINE |ES_READONLY|
WS_HSCROLL | WS_VSCROLL,
x0,y0,w,h,
hW,(HMENU)ID,hInst,NULL);
}
//---------------------------------------------------------------------------
//向多行文本框中添加文本
void Puts(HWND hW,int ID_EDIT,char *str)
{
int nLen=GetWindowTextLength(GetDlgItem(hW,ID_EDIT));
SendMessage(GetDlgItem(hW,ID_EDIT),EM_SETSEL,nLen,nLen);
SendMessage(GetDlgItem(hW,ID_EDIT),EM_REPLACESEL,TRUE,(long)(LPCTSTR)str);
nLen=GetWindowTextLength(GetDlgItem(hW,ID_EDIT));
SendMessage(GetDlgItem(hW,ID_EDIT),EM_SETSEL,nLen,nLen);
SendMessage(GetDlgItem(hW,ID_EDIT),EM_REPLACESEL,TRUE,(long)(LPCTSTR)"\r\n");
}
//---------------------------------------------------------------------------
//按钮
#define BUTTON1 501
#define BUTTON2 502
//---------------------------------------------------------------------------
//单行编辑框
#define EDIT1 601
#define EDIT2 602
#define EDIT3 603
#define EDIT4 604
//---------------------------------------------------------------------------
//多行编辑框
#define MEMO1 701
//---------------------------------------------------------------------------
WSADATA ws;
SOCKET Ss,Cs;
struct sockaddr_in SA,CA;
char aa[];
char bb[];
int d;
//---------------------------------------------------------------------------
//消息处理
LRESULT CALLBACK WndProc(HWND hW, UINT msg, WPARAM wP, LPARAM lP)
{
int i;
switch (msg)
{
case WM_DESTROY: //关闭程序触发事件
WSAAsyncSelect(Ss, hW, , ); //向Windows注销Socket触发事件
closesocket(Cs); //释放连接
WSACleanup( ); //卸载动态连接库WinSock DLL
PostQuitMessage();
break;
case WM_CREATE: //程序初始化触发事件
WSAStartup(0x0101,&ws); //装载动态连接库WinSock DLL
CreateButton("Send",,,,,BUTTON1,hW,hInst); //发送信息按钮
CreateButton("Conn",,,,,BUTTON2,hW,hInst); //连接Chat Server按钮
CreateEdit("127.0.0.1",,,,,EDIT2,hW,hInst); //Chat Server的IP地址输入框
CreateEdit("",,,,,EDIT3,hW,hInst); //Chat Server的Port地址输入框
CreateEdit("Name",,,,,EDIT4,hW,hInst); //用户登录名输入框
CreateEdit("Hello!",,,,,EDIT1,hW,hInst); //发送信息输入框
CreateMemo("Info.", ,,,,MEMO1,hW,hInst); //接受信息显示窗口
SetFocus(GetDlgItem(hW,BUTTON2));
EnableWindow(GetDlgItem(hW,BUTTON1),FALSE);
break;
case WM_USER+: //Socket触发事件
switch(LOWORD(lP))
{
case FD_CONNECT: //Chat Server的建立连接应答
// Puts(hW,MEMO1,"FD_CONNECT->Ok!");
break;
case FD_READ: //收到Chat Server信息
d=recv(wP,bb,sizeof(bb),);//wP=Cs //读接收缓冲区
bb[d]=;
wsprintf(aa,"FD_READ->:%s",bb);
Puts(hW,MEMO1,bb);
break;
case FD_CLOSE: //Chat Server的释放连接请求
Puts(hW,MEMO1,"Server Stop!");
break;
}
break;
case WM_COMMAND: //控件触发事件
switch(wP)
{
case BUTTON1: //按下发送信息按钮
GetDlgItemText(hW,EDIT1,bb,sizeof(bb));
send(Cs,bb,strlen(bb),); //向Chat Server发送信息
break;
case BUTTON2: //按下连接Chat Server按钮
GetDlgItemText(hW,EDIT2,aa,sizeof(aa));
GetDlgItemText(hW,EDIT3,bb,sizeof(bb));
Cs = socket(PF_INET, SOCK_STREAM, ); //创建TCP套接字Socket
SA.sin_family = PF_INET; //远程Chat Server的属性:地址类型 AF_INET for Internet
SA.sin_port = htons(atoi(bb)); //远程Chat Server的属性:端口
SA.sin_addr.s_addr =inet_addr(aa); //远程Chat Server的属性:IP地址
d=sizeof(SA);
i=connect(Cs,(struct sockaddr *)&SA,d); //连接Chat Server
if(!i)
{ //连接Chat Server成功
EnableWindow(GetDlgItem(hW,BUTTON2),FALSE);
EnableWindow(GetDlgItem(hW,BUTTON1),TRUE);
EnableWindow(GetDlgItem(hW,EDIT2),FALSE);
EnableWindow(GetDlgItem(hW,EDIT3),FALSE);
EnableWindow(GetDlgItem(hW,EDIT4),FALSE);
WSAAsyncSelect(Cs,hW,WM_USER+,FD_CONNECT|FD_READ|FD_CLOSE);//向Windows注册Socket触发事件
GetDlgItemText(hW,EDIT4,bb,sizeof(bb));
send(Cs,bb,strlen(bb),); //连接成功后,向Chat Server发送用户登录名
}
else
Puts(hW,MEMO1,"connect fail!"); //连接Chat Server失败
Beep(,);
break;
}
break;
}
return DefWindowProc(hW,msg,wP,lP);
}
//--------------------------------------------------------------

chatcli.cpp

第四部分:抓包工具抓取TCP三次握手建立连接的报文

采用方案2:访问百度网站 然后分析tcp报文

1.整体看三次握手过程

首先我们给百度发syn报文

然后百度给我们发syn+ACK报文

最后我们给百度发ACK报文

2.第一步

3.第二步

4.第三步

5.TCP报文格式

源端口: 数据发送方的端口号。

目的端口: 数据接受方的端口号。

序号:本数据报文中的的第一个字节的序号(在数据流中每个字节都对应一个序号)。

确认号:希望收到的下一个数据报文中的第一个字节的序号。

数据偏移:表示本报文数据段距离报文段有多远。

保留:顾名思义,用来保留给以后用的。

紧急比特URG:当值为1时表示次报文段中有需要紧急处理。

确认比特ACK:值为1时确认号有效,值为0时确认号无效。

复位比特RST:值为1时表示TCP连接存在严重的错误,需要重新进行连接。

同步比特SYN:值为1表示这是一个连接请求或连接接受报文。

终止比特FIN: 值为1表示要发送的数据报已经发送完毕,需要释放传送连接。

窗口字段:TCP连接的一端根据缓存空间的大小来确定自己接受窗口的大小,限制发送放的窗口上限。

检验和:用来检验首部和数据两部分的正确性。

紧急指针字段:本报文紧急数据的最后一个字节的序号。

6.UDP报文格式

UDP长度:UDP报文的字节长度(包括首部和数据)。

UDP校验和: 检验UDP首部和数据部分的正确性。

7.IP报文格式

版本:指IP协议的版本。

首部长度:首部的长度

服务类型:如下图:

优先级用来区别优先级别不同的IP报文。

D表示要求有更低的时延。

T表示要求有更高的吞吐量。

R表示要求有更高的可靠性。

总长度:报文的长度。

标识:由于数据报长度超过传输网络的MTU(最大传输单元)而必须分片,这个标识字段的值被复制到所有数据报分片的标识字段中,使得这些分片在达到最终的目的地时可以依照标识字段的内容重新组成原先的数据报。

标志:最低位是MF,MF=1时,表示后面还有分片。

中间位的DF,DF=1时,表示不能分片。

片偏移: 和前面的数据分片相关,是本分片在原先数据报文中相对首位的偏移位。

生存时间:数据报在网络中存活的时间,所允许通过的路由器的最大数量,没通过一个路由器,该值自动减一,如果数值为0,路由器就可以把该数据报丢弃。

协议: 指出数据报携带的数据是使用何种协议,以便目的主机的IP层能知道次数据报上交到哪一个进程(不同协议有一个专门不同的进程处理)。

首部校验位和:对首部进行校验运算。

校验方法 : 在发送端,将IP数据报首部划分为多个16位的二进制序列,并将首部校验和字段置为0,

用反码运算将所有16位序列对位相加后,将得到多的和的反码写入首部校验和字段。

接收端接收到数据报后,将数据报首部的所有字段组织成多个16位的二进制序列,再使用反码运算相加一次

将得到的结果取反。如果结果为0代表没出错,否则出错。

源地址:发送数据报的节点地址。

目的地址:接受数据报的节点地址。

实验一:基于Winsock完成简单的网络程序开发的相关教程结束。