我自己记录的Socket笔记
2.网络技术 http://www.s8s8.net/index.php junjianns didadi junjianns@yahoo.com.cn
4.巨果操作系统 http://www.mlg.com.cn/bbs/index.asp junjianns didadi junjianns@yahoo.com.cn
四. 网络通讯学习过程:
1.在书中多线程界面的例子中,如何结束主线程中的界面,而主线程不结束,因为主线程一结束,所有线程都结束.
2.文件映像笔记.在发送端和接收端的定义文件:
typedef struct tagFileMappingStruct
{
int cou;
TCHAR str[128];
}FILEMAPPINGSTRUCT, *PFILEMAPPINGSTRUCT;
PFILEMAPPINGSTRUCT m_pFileMappingStruct;
HANDLE m_hFileMapping;
在发送端和接收端的实现文件的初始化:
m_hFileMapping=::CreateFileMapping(INVALID_HANDLE_VALUE,NULL,PAGE_READWRITE,0,sizeof(FILEMAPPINGSTRUCT),"xh");
m_pFileMappingStruct=(PFILEMAPPINGSTRUCT)::MapViewOfFile(m_hFileMapping,FILE_MAP_ALL_ACCESS,0,0,sizeof(FILEMAPPINGSTRUCT));
m_pFileMappingStruct->cou=0;
在发送端和接收端的实现文件的销毁中:
::UnmapViewOfFile(m_pFileMappingStruct);
::CloseHandle(m_hFileMapping);
在发送代码中:
TCHAR strTemp[128];
GetDlgItemText(IDC_EDIT1,strTemp,sizeof(strTemp));
if(strTemp==m_pFileMappingStruct->str)
m_pFileMappingStruct->cou+=1; //记录这个数据被写了几次.
else
{
m_pFileMappingStruct->cou=1;
strcpy(m_pFileMappingStruct->str,strTemp);
}
在接收代码中:
TCHAR strTemp[128];
GetDlgItemText(IDC_EDIT1,strTemp,sizeof(strTemp));
if(strTemp==m_pFileMappingStruct->str)
m_pFileMappingStruct->cou-=1; //记录这个数据被读了几次.
else
{
m_pFileMappingStruct->cou=-1;
strcpy(strTemp,m_pFileMappingStruct->str);
}
SetDlgItemText(IDC_EDIT1,strTemp);
3.WM_COPYDATA的应用.在发送代码中:
CWnd* p = CWnd::FindWindow(NULL, TEXT("测试 WM_COPYDATA 消息:接收方"));
COPYDATASTRUCT s;
s.cbData = (text.GetLength() + 1) * sizeof(TCHAR);
s.lpData = (LPVOID)LPCTSTR(text);
p->SendMessage(WM_COPYDATA, (WPARAM)GetSafeHwnd(), (LPARAM)&s);
在接收端在响应WM_COPYDATA消息的代码中.
LPCTSTR strText=(LPCTSTR)(pCopyDataStruct->lpData); //收到了.
4.用剪贴板.在定义文件中定义:
typedef struct tagSelection
{
int startOff; // start offset for selection
int endOff; // end offset for selection
}SELECTION, *PSELECTION;
在拷贝代码中:
CString t;
GetDlgItemText(IDC_TEXT, t);
HGLOBAL h = ::GlobalAlloc(GMEM_MOVEABLE, sizeof(SELECTION)); //分配内存
PSELECTION p = (PSELECTION)::GlobalLock(h); //锁定全局内存,返回指向内存块内容的第一个字节
((CEdit*)GetDlgItem(IDC_TEXT))->GetSel(p->startOff, p->endOff); //为p->startOff,p->endOff赋值.
::GlobalUnlock(h);
HGLOBAL hText = ::GlobalAlloc(GMEM_MOVEABLE,(t.GetLength() + 1) * sizeof(TCHAR));
LPTSTR pText = (LPTSTR)::GlobalLock(hText);
::_tcscpy(pText, LPCTSTR(t));
::GlobalUnlock(hText);
OpenClipboard();
::EmptyClipboard();
::SetClipboardData(CF_TEXT, hText);
::SetClipboardData(m_nSelectionFormat, h);
::CloseClipboard();
在粘贴代码中:
OpenClipboard();
if (::IsClipboardFormatAvailable(CF_TEXT))
{
HGLOBAL h = (HGLOBAL)::GetClipboardData(CF_TEXT);
LPCTSTR p = (LPCTSTR)::GlobalLock(h);
SetDlgItemText(IDC_TEXT, p);
::GlobalUnlock(h);
if (::IsClipboardFormatAvailable(m_nSelectionFormat))
{
HGLOBAL h = (HGLOBAL)::GetClipboardData(m_nSelectionFormat);
PSELECTION p = (PSELECTION)::GlobalLock(h);
((CEdit*)GetDlgItem(IDC_TEXT))->SetSel(p->startOff, p->endOff);
::GlobalUnlock(h);
}
}
::CloseClipboard();
5.使用管道.形式类似于UDP,在接收端的定义文件定义:
#define __PIPE_NAME__ TEXT("\\\\.\\pipe\\Message Pipe")
#define STRINGSIZE 256
HANDLE m_hPipe;
OVERLAPPED m_o;
在接收端的实现文件,创建命名管道.准备接收管道信息.
m_hPipe = NULL;
::memset(&m_o, 0, sizeof(OVERLAPPED)); //必须初始化.
m_hPipe=::CreateNamedPipe(__PIPE_NAME__, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 1, STRINGSIZE, STRINGSIZE, 50, NULL);
m_o.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
while (TRUE)
{
::ConnectNamedPipe(m_hPipe, &m_o); //等待接收一个命名管道的连接.立即返回
while (::WaitForSingleObject(m_o.hEvent, 50) == WAIT_TIMEOUT) //循环等待50毫秒.直到m_o.hEvent变为有信号量.
{
MSG msg;
while (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
if (!::TranslateMessage(&msg)) ::DispatchMessage(&msg);
}
TCHAR buf[STRINGSIZE];
DWORD fetched;
::ResetEvent(m_o.hEvent); //有一个连接后把m_o.hEvent信号变为无信号状态.
::ReadFile(m_hPipe, buf, STRINGSIZE, &fetched, &m_o); //读完后将m_o.hEvent信号变为有信号状态.
SetDlgItemText(IDC_MSG, buf);
SetDlgItemText(IDC_MSG2, ::_tcsupr(buf));
::ResetEvent(m_o.hEvent);
::WriteFile(m_hPipe, buf, (::_tcslen(buf) + 1) * sizeof(TCHAR), &fetched, &m_o); //写完后将m_o.hEvent信号变为有信号状态.
::DisconnectNamedPipe(m_hPipe);
}
在发送端的实现文件中:
CString x;
GetDlgItemText(IDC_MSG,x);
::CallNamedPipe(__PIPE_NAME__,(LPVOID)LPCTSTR(x),(x.GetLength()+1)*sizeof(TCHAR),buf,STRINGSIZE,&read,NMPWAIT_USE_DEFAULT_WAIT)
五. CChatServer程序分析.Socket中的多线程.
1.CIniFile类,不如改用Serialize()省事,方便.
2.Message结构.
3.CMyTreeView类,
4.CClientSocket
5.CServerSocket
6.CparseMessage 自定义消息处理中心.
7.MFC中的Socket处理步骤:
Server端,从CSocket派生类CServerSocket和CClientSocket,
CServerSocket m_skServerSocket; //声明部分定义.
AfxSocketInit();
m_skServerSocket.Create(port);
m_skServerSocket.Listen();
m_skServerSocket.Accept(CClientSocket); //可以在CServerSocket中重写OnAccept用以控制把多线程中的CCriticalSection加锁.
Receive(&Message,sizeof(Message)); //在CClientSocket类重写OnReceive,处理接收的信息后,把在CServerSocket中重写的OnAccept函数中的CCriticalSection解锁.
Cient端,从CSocket派生类CMainSocket,
CMainSocket m_skMainSocket;//声明部分定义.
AfxSocketInit();
m_skMainSocket.Create();
m_skMainSocket.Connect(ServerIp,ServerPort)
m_skMainSocket.Send(&Message,sizeof(Message));//发送数据
Receive(&Message,sizeof(Message));//在CMainSocket中重写OnReceive,处理接收的信息.
另外的学习:
1.关于复制构造函数.在类的定义部分 public:CMyClass(const CMyClass & c);在类的实现部分对两个类中的成员变量进行赋值.
2.关于CCriticalSection.我初步认为,要把它声明成全局的,在用的时候把它Lock(),用完后把它UnLock(),在Lock()和UnLock()
中间的所有对象,变量在CPU执行的这段代码期间,其它线程不可同时访问这段代码中的对象,变量了.
3.引用也即别名,也是取址.
4.分析代码,先要弄清各变量的意义,以及变量在程序之间的联系.
一.函数:
htonl:把主机字节顺序转换为网络字节顺序.转换的类型是u_long.用在SOCKADDR_IN::sin_addr::S_un::S_addr值中.
该值存储的是u_long型的网络字节顺充的IP地址.
htons:把主机字节顺序转换为网络字节顺序.转换的类型是u_short.用在SOCKADDR_IN::sin_port值中,
该值存领教的是u_short型的网络字节顺序的端口号.
inet_ntoa:把一个 in_addr 结构中的IPV4网络地址转换为字符串格式的点分IP地址.
inet_addr
二.注意.
1.在accept的时候,用
int d=sizeof(ClientAddr);
SOCKET accpSock=accept(s,(sockaddr*)&ClientAddr,&d );
2.分配内存.
CONNECTION_OBJ *newobj=NULL; //CONNECTION_OBJ是一个自定义结构.
// Allocate the object
newobj = (CONNECTION_OBJ *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CONNECTION_OBJ));
3.
在WaitForMultipleEvents函数中,网络事件触发了与一个套接字关联在一起的事件对象,工作状态便从未传信变成传信状态.
在WaitForMultipleObjects函数中,监视一系列线程(用CreateThread创建)时是怎样将未传信变成传信状态的.
解:当线程正在运行时是未传信状态.线程正常退出后是传信状态. See Synchronization Objects.
|
作者:NewSea 出处:http://newsea.cnblogs.com/
QQ,MSN:iamnewsea@hotmail.com 如无特别标记说明,均为NewSea原创,版权私有,翻载必纠。欢迎交流,转载,但要在页面明显位置给出原文连接。谢谢。 |

浙公网安备 33010602011771号