实验一:基于Winsock完成简单的网络程序开发
第一部分:简答的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完成简单的网络程序开发的更多相关文章
- 基于RDD实现简单的WordCount程序
写在前面 因为觉得自己的代码量实在是太少了,所以,想着,每周至少写5个小的demo程序.现在的想法是,写一些Spark,Storm,MapReduce,Flume,kafka等等单独或组合使用的一些小 ...
- Java开发桌面程序学习(九)——JavaFxTemplate JavaFx模版 更简单进行JavaFx程序开发
JavaFxTemplate 使用说明 项目基于maven,请确保maven配置成功,否则,可能会出现问题 项目内置了commons-io的jar包,Jfoenix的jar包以及常用的工具类JFxUt ...
- 基于go语言结合微信小程序开发的微商城系统
最近在慕课网上录制了一门<Golang微信小程序微商城系统原型>,这门免费课程特别适合在校大学生或者刚毕业的大学生,go语言初学者以及想要从事微商城开发项目入门的小伙伴们来学习.在课程当中 ...
- 基于OpenCV的图书扫描识别程序开发
1.AndroidStudio环境配置 https://www.cnblogs.com/little-monkey/p/7162340.html
- 通过汇编一个简单的C程序,分析汇编代码理解计算机是如何工作的
秦鼎涛 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 实验一 通过汇编一个简单的C程序,分析汇编代码 ...
- 基于RxJava2+Retrofit2简单易用的网络请求实现
代码地址如下:http://www.demodashi.com/demo/13473.html 简介 基于RxJava2+Retrofit2实现简单易用的网络请求,结合android平台特性的网络封装 ...
- 一只简单的网络爬虫(基于linux C/C++)————浅谈并发(IO复用)模型
Linux常用的并发模型 Linux 下设计并发网络程序,有典型的 Apache 模型( Process Per Connection ,简称 PPC ), TPC ( Thread Per Conn ...
- R-FCN:基于区域的全卷积网络来检测物体
http://blog.csdn.net/shadow_guo/article/details/51767036 原文标题为“R-FCN: Object Detection via Region-ba ...
- 基于modelsim-SE的简单仿真流程—上
基于modelsim-SE的简单仿真流程 编写RTL功能代码 要进行功能仿真,首先得用需要仿真的模块,也就是RTL功能代码,简称待测试的模块,该模块也就是在设计下载到FPGA的电路.一个电路模块想要有 ...
随机推荐
- L - Oil Deposits
很清新的一道题,搜索里面最基础的题目,深搜广搜都可以.....不过还是喜欢深搜,写起来简单>.. //////////////////////////////////////////////// ...
- poj4474 Scout YYF I(概率dp+矩阵快速幂)
Scout YYF I Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 4100 Accepted: 1051 Descr ...
- XPath与Xquery
XPath 和 XQuery 在某些方面很相似.XPath 还是 XQuery 完整不可分割的一部分.这两种语言都能够从 XML 文档或者 XML 文档存储库中选择数据.本文简要介绍了 XPath 和 ...
- 面向GC的Java编程
转自http://hellojava.info/?p=341 HelloJava微信公众账号网站 面向GC的Java编程 Leave a reply 这是内部一个同事(沐剑)写的文章,国外有一家专门做 ...
- JAVA的可变类与不可变类
转自: http://www.blogjava.net/hilor/articles/150610.html 可变类和不可变类(Mutable and Immutable Objects)的初步定义: ...
- Java同步工具类总结
先谈谈闭锁和栅栏的区别: 1.关键区别在于,所有线程必须同时到达栅栏位置,才能继续执行. 2.闭锁用于等待某一个事件的发生,举例:CountDownLatch中await方法等待计数器为零时,所有事件 ...
- LTTng调试: 一个系统软件工程师的随手涂鸦
http://nanxiao.me/install-lttng/ http://packages.efficios.com/ http://lttng.org/ http://lttng.org/do ...
- Linux下得到显示屏参数的方法
先安装一个软件,然后使用权ddcprobe可以查看当前支持的分辨率和刷新频率#sudo apt-get install xresprobe运行 #sudo ddcprobe会得到下面的信息vbe: V ...
- 案例:利用累加器计算前N个学生的总成绩和平均成绩
/* *录入N个学生的成绩,并求出这些学生的总成绩和平均成绩! * */ import java.util.Scanner; public class SumTest{ public static v ...
- (转)dedecms代码详解 很全面
dedecms代码研究(1)开篇dedecms 相信大家一定都知道这个cms 系统,功能比较强大,有比较完善的内容发布,还有内容静态化系统,还有就是它有自己独特的标签系统和模板系统.而模板系统也是其他 ...