开启服务器功能:
void OnServerOpen() //开启服务器功能
{
WSADATA wsaData
int iErrorCode
char chInfo[64]
if (WSAStartup(WINSOCK_VERSION, &wsaData)) //调用Windows Sockets DLL
{ MessageBeep(MB_ICONSTOP)
MessageBox("Winsock无法初始化!", AfxGetAppName(), MB_OK|MB_ICONSTOP)
WSACleanup()
return}
else
WSACleanup()
if (gethostname(chInfo, sizeof(chInfo)))
{ ReportWinsockErr("\n无法获取主机!\n ")
return}
CString csWinsockID = "\n==>>服务器功能开启在端口:No. "
csWinsockID += itoa(m_pDoc->m_nServerPort, chInfo, 10)
csWinsockID += "\n"
PrintString(csWinsockID)//在程序视图显示提示信息的函数,读者可自行创建
m_pDoc->m_hServerSocket=socket(PF_INET, SOCK_STREAM, DEFAULT_PROTOCOL)
//御贺嫌创建服务器端Socket,类型为SOCK_STREAM,面向连接镇手的通信
if (m_pDoc->m_hServerSocket == INVALID_SOCKET)
{ ReportWinsockErr("无法创建服务器socket!")
return}
m_pDoc->m_sockServerAddr.sin_family = AF_INET
m_pDoc->m_sockServerAddr.sin_addr.s_addr = INADDR_ANY
m_pDoc->m_sockServerAddr.sin_port = htons(m_pDoc->m_nServerPort)
if (bind(m_pDoc->m_hServerSocket, (LPSOCKADDR)&m_pDoc->m_sockServerAddr,
sizeof(m_pDoc->m_sockServerAddr)) == SOCKET_ERROR) //与选定的端口绑定
{ReportWinsockErr("无法绑定服务器socket!")
return}
iErrorCode=WSAAsyncSelect(m_pDoc->m_hServerSocket,m_hWnd,
WM_SERVER_ACCEPT, FD_ACCEPT)
//设定服务器相应的网络事件为FD_ACCEPT,即连接请求,
// 产生相应传递给窗口的消息为WM_SERVER_ACCEPT
if (iErrorCode == SOCKET_ERROR)
{ ReportWinsockErr("WSAAsyncSelect设定失败!")
return}
if (listen(m_pDoc->m_hServerSocket, QUEUE_SIZE) == SOCKET_ERROR) //开始监听客户连接请求
{ReportWinsockErr("服务器socket监听失败!")
m_pParentMenu->EnableMenuItem(ID_SERVER_OPEN, MF_ENABLED)
return}
m_bServerIsOpen = TRUE//监视服务器是否打开的变拍租量
return
}
响应客户发送聊天文字到服务器:ON_MESSAGE(WM_CLIENT_READ, OnClientRead)
LRESULT OnClientRead(WPARAM wParam, LPARAM lParam)
{
int iRead
int iBufferLength
int iEnd
int iRemainSpace
char chInBuffer[1024]
int i
for(i=0(i
//MAXClient是服务器可响应连接的最大数目
{}
if(i==MAXClient) return 0L
iBufferLength = iRemainSpace = sizeof(chInBuffer)
iEnd = 0
iRemainSpace -= iEnd
iBytesRead = recv(m_aClientSocket[i], (LPSTR)(chInBuffer+iEnd), iSpaceRemaining, NO_FLAGS)
//用可控缓冲接收函数recv()来接收字符
iEnd+=iRead
if (iBytesRead == SOCKET_ERROR)
ReportWinsockErr("recv出错!")
chInBuffer[iEnd] = '\0'
if (lstrlen(chInBuffer) != 0)
{PrintString(chInBuffer)//服务器端文字显示
OnServerBroadcast(chInBuffer)//自己编写的函数,向所有连接的客户广播这个客户的聊天文字
}
return(0L)
}
对于客户断开连接,会产生一个FD_CLOSE消息,只须相应地用closesocket()关闭相应的Socket即可,这个处理比较简单。
4.2客户端代码
连接到服务器:
void OnSocketConnect()
{ WSADATA wsaData
DWORD dwIPAddr
SOCKADDR_IN sockAddr
if(WSAStartup(WINSOCK_VERSION,&wsaData)) //调用Windows Sockets DLL
{MessageBox("Winsock无法初始化!",NULL,MB_OK)
return
}
m_hSocket=socket(PF_INET,SOCK_STREAM,0)//创建面向连接的socket
sockAddr.sin_family=AF_INET//使用TCP/IP协议
sockAddr.sin_port=m_iPort//客户端指定的IP地址
sockAddr.sin_addr.S_un.S_addr=dwIPAddr
int nConnect=connect(m_hSocket,(LPSOCKADDR)&sockAddr,sizeof(sockAddr))//请求连接
if(nConnect)
ReportWinsockErr("连接失败!")
else
MessageBox("连接成功!",NULL,MB_OK)
int iErrorCode=WSAAsyncSelect(m_hSocket,m_hWnd,WM_SOCKET_READ,FD_READ)
//指定响应的事件,为服务器发送来字符
if(iErrorCode==SOCKET_ERROR)
MessageBox("WSAAsyncSelect设定失败!")
}
接收服务器端发送的字符也使用可控缓冲接收函数recv(),客户端聊天的字符发送使用数据可控缓冲发送函数send(),这两个过程比较简单,在此就不加赘述了。
//服务端://服务器接受线程数据
UINT CTcpSrvDlg::ReThreadFunc(LPVOID lParam)
{
CTcpSrvDlg *pDlgSrv = (CTcpSrvDlg*)lParam
WORD wVersionRequested//当前网络Socket版本号
WSADATA wsaData//定义当前网络信息对象
int err
int iError
CString str
wVersionRequested = MAKEWORD( 1, 1 )//(1.1)版本
//===1、初始化网络设备环境===
err = WSAStartup( wVersionRequested, &wsaData )
//如果WSAStartup返回值为0,则初始化成功
if ( err != 0 )
{
return 1L
}
//如果网络环境版本不对应,则清空网络设备环境并结束芹嫌姿当前线程
if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 )
{
AfxMessageBox("版本不匹配")
//清空网络设备环境
::WSACleanup()
return 1L
}
//===2、加载套接字===
SOCKET socketSvr = ::socket(AF_INET/*通信区域*/, SOCK_STREAM/*数据流式——TCP*/, 0)
if (INVALID_SOCKET == ::WSAGetLastError())
{
AfxMessageBox("加载套接字失败")
::WSACleanup()
::closesocket(socketSvr)
return 1L
}
//===3、套接字绑定
//者基初始化当前主机地址信息结构体对象
SOCKADDR_IN addSrv
addSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY)//允许任何IP的主机与之相连
addSrv.sin_family = AF_INET//通信网际域
addSrv.sin_port = htons(7000)//0——65355端口,自定义要大一些>1000
iError = ::bind(socketSvr, (SOCKADDR*)&addSrv, sizeof(SOCKADDR_IN))
/嫌绝/校验是否绑定成功
if (SOCKET_ERROR == iError)
{
AfxMessageBox("套接字绑定失败")
::WSACleanup()
::closesocket(socketSvr)
return 1L
}
//===监听===
iError = ::listen(socketSvr, SOMAXCONN/*等待连接堆内的最大来访者个数,
如果设置为SOMAXCONN,
则下层的服务提供者负责将套接字设置backlog值为最大的合理的值。*/
)
if (SOCKET_ERROR == iError)
{
AfxMessageBox("监听失败")
::WSACleanup()
::closesocket(socketSvr)
return 1L
}
//===5、接受请求的客户机的套接字信息===
SOCKET sockClient
SOCKADDR_IN addrClient
int iAddrLen = sizeof(SOCKADDR_IN)
while (1)
{
//接受对方的套接字信息
::accept(socketSvr/*服务器接受*/, (SOCKADDR*)&addrClient, &iAddrLen)
//===6、接受客户端发过来的数据===
char recvBuf[100]
iError = ::recv(sockClient, recvBuf, 100, 0)
if(SOCKET_ERROR == iError)
{
AfxMessageBox("数据接受失败")
}
//将接受过来的数据显示ListBox中
str.Format("%s",recvBuf)
pDlgSrv->m_lbRecv.AddString(str)
}
::closesocket(socketSvr)
::WSACleanup()
return 1L
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)