网络编程之select 模式开发实例
来源:互联网 发布:金融数据接口 编辑:程序博客网 时间:2024/05/09 20:49
在网络上看到太多关于select i/o用法,都不是非常的详细。
经过摸索,把我实现的例子张贴上来,供大家参考。
描述:
服务器:实现并发tcp服务器,最多允许64 个客户端连接。
客户端:与服务器建立tcp连接,发送数据给服务器。服务器接收数据。
服务器代码:(红色为我的代码)
// SelectServerDlg.h : header file
//
#if !defined(AFX_SELECTSERVERDLG_H__3D5E9C67_8737_4E23_9734_0F196495ED30__INCLUDED_)
#define AFX_SELECTSERVERDLG_H__3D5E9C67_8737_4E23_9734_0F196495ED30__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
/////////////////////////////////////////////////////////////////////////////
// CSelectServerDlg dialog
UINT proc(LPVOID lParam);
class CSelectServerDlg : public CDialog
{
// Construction
public:
CSelectServerDlg(CWnd* pParent = NULL); // standard constructor
CWinThread *pThread;
BOOL bRun;
// Dialog Data
//{{AFX_DATA(CSelectServerDlg)
enum { IDD = IDD_SELECTSERVER_DIALOG };
// NOTE: the ClassWizard will add data members here
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CSelectServerDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
HICON m_hIcon;
// Generated message map functions
//{{AFX_MSG(CSelectServerDlg)
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
afx_msg void OnClose();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_SELECTSERVERDLG_H__3D5E9C67_8737_4E23_9734_0F196495ED30__INCLUDED_)
————————————————————————————————————————
//SelectServerDlg.cpp代码
BOOL CSelectServerDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
WSAData wsadata;
WORD wVersionRequest;
wVersionRequest=MAKEWORD(2,2);
if(WSAStartup(wVersionRequest,&wsadata)!=0)
TRACE("没有DLL可用\n");
if(LOBYTE(wsadata.wVersion) != 2 || HIBYTE(wsadata.wVersion) != 2)
{
AfxMessageBox("socket dll 启动失败");
WSACleanup();
}
pThread = AfxBeginThread(proc, this);
return TRUE; // return TRUE unless you set the focus to a control
}
——————————————————————————————————————
//服务器线程
UINT proc(LPVOID lParam)
{
try{
fd_set rset;
CSelectServerDlg *pDlg = (CSelectServerDlg*)lParam;
struct sockaddr_in seraddr,cliaddr;
int client[FD_SETSIZE],listensock;
FD_ZERO(&rset);
seraddr.sin_addr.s_addr = inet_addr("192.168.1.24");
seraddr.sin_family = AF_INET;
seraddr.sin_port = htons(6500);
memset(seraddr.sin_zero, 0, 8);
listensock = socket(AF_INET, SOCK_STREAM, 0);
TRACE("listen socket :%d\n", listensock);
bind(listensock, (struct sockaddr *)&seraddr, sizeof(seraddr));
listen(listensock, 20);
for(int i = 0; i<FD_SETSIZE; i++)
client[i] = -1;
pDlg->bRun = TRUE;
int nReady;
struct timeval timeout;
int isset;
int err;
int maxfd;
int connfd;
int clilen;
maxfd = listensock;
char buf[1024];
int recvbytes = 0;
memset(buf, 0, 1024);
while(pDlg->bRun){
Sleep(1);
timeout.tv_sec = 0;
timeout.tv_usec = 10;
/*
listen socket 加入fdset
*/
FD_SET(listensock, &rset);
for(int n = 0; n<FD_SETSIZE; n++)
{
if(client[n]>0){
FD_SET(client[n], &rset);
if(client[n] > maxfd)
maxfd = client[n];
}
}
nReady = select(maxfd+1, &rset, NULL, NULL, &timeout);
if(nReady == 0)
//TRACE("select fun time out\n");
;
else if(nReady == -1)
{
TRACE("socket error\n");
err = WSAGetLastError();
switch(err)
{
case WSANOTINITIALISED:
TRACE("WSANOTINITIALISED 未初始化\n");
break;
case WSAEFAULT:
TRACE("WSAEFAULT\n");
break;
case WSAENETDOWN:
TRACE("WSAENETDOWN\n");
break;
case WSAEINVAL:
TRACE("WSAEINVAL\n");
break;
case WSAEINTR:
TRACE("WSAEINTR\n");
break;
case WSAEINPROGRESS:
TRACE("WSAEINPROGRESS\n");
break;
case WSAENOTSOCK:
TRACE("WSAENOTSOCK\n");
break;
}
}
else
{
/*
测试已经建立连接的socket
*/
unsigned long ul = 1;
for(int j = 0; j<FD_SETSIZE; j++)
{
if(client[j]>0)
{
memset(buf,0,1024);
isset = FD_ISSET(client[j],&rset);
if(isset)
{
//ioctlsocket(client[j], FIONBIO, &ul);
recvbytes = recv(client[j], buf, 1024, NULL);
if(recvbytes>0)
TRACE("from socket: %d,接收字节数:%d,%s\n",client[j], recvbytes, buf);
else if(recvbytes == 0)
{
closesocket(client[j]);
TRACE("client socket :%d closed! \n",client[j]);
client[j] = -1;
}
}
}
}
/*
测试是否有连接?
*/
isset = FD_ISSET(listensock, &rset);
FD_ZERO(&rset);
if(isset)
{
TRACE("conncetion.... \n");
clilen = sizeof(cliaddr);
connfd = accept(listensock,(struct sockaddr *)&cliaddr, &clilen);
TRACE("connection comes from ip:%d.%d.%d.%d\n",cliaddr.sin_addr.S_un.S_un_b.s_b1,
cliaddr.sin_addr.S_un.S_un_b.s_b2,
cliaddr.sin_addr.S_un.S_un_b.s_b3,
cliaddr.sin_addr.S_un.S_un_b.s_b4);
for(int s=0; s<FD_SETSIZE; s++){
if(client[s]<0){
client[s] = connfd;
break;
}
}
TRACE("con number:%d\n", s+1);
TRACE("socket id:");
for(int k = 0; k < FD_SETSIZE; k++)
{
if(client[k]>0)
TRACE("%d,",client[k]);
}
TRACE("\n");
}
}
}
}
catch (...) {
TRACE("exception.........!!\n");
}
return TRUE;
}
——————————————————————————————————
//客户端代码:
BOOL CTcpClientDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
WSAData wsadata;
WORD wVersionRequest;
wVersionRequest=MAKEWORD(2,2);
if(WSAStartup(wVersionRequest,&wsadata)!=0)
TRACE("没有DLL可用\n");
if(LOBYTE(wsadata.wVersion)!=2||HIBYTE(wsadata.wVersion)!=2)
{
AfxMessageBox("socket dll 启动失败");
WSACleanup();
}
serveraddr.sin_family=AF_INET;
serveraddr.sin_port=htons(6500);
serveraddr.sin_addr.S_un.S_un_b.s_b1=192;
serveraddr.sin_addr.S_un.S_un_b.s_b2=168;
serveraddr.sin_addr.S_un.S_un_b.s_b3=1;
serveraddr.sin_addr.S_un.S_un_b.s_b4=24;
clientsocket=socket(AF_INET,SOCK_STREAM,0);
return TRUE; // return TRUE unless you set the focus to a control
}
void CTcpClientDlg::OnSend()
{
// TODO: Add your control notification handler code here
nResult=connect(clientsocket,(struct sockaddr *)&serveraddr,sizeof(serveraddr));
if(nResult != SOCKET_ERROR)
{
TRACE("连接成功\n");
char *szSend="123456789";
nResult=sendto(clientsocket,szSend,9,0,(struct sockaddr*)&serveraddr,sizeof(serveraddr));
if(nResult != SOCKET_ERROR)
{
TRACE("发送成功\n");
}
}
}
void CTcpClientDlg::OnButton2()
{
// TODO: Add your control notification handler code here
closesocket(clientsocket);
}
void CTcpClientDlg::OnButton3()
{
// TODO: Add your control notification handler code here
char *szSend="123456789";
nResult=sendto(clientsocket,szSend,9,0,(struct sockaddr*)&serveraddr,sizeof(serveraddr));
if(nResult != SOCKET_ERROR)
{
TRACE("发送成功\n");
}
}
(完)
- 网络编程之select 模式开发实例
- 网络编程之select模式
- 网络编程之Select模式
- 网络编程第一篇之Select模式
- windows网络编程之Winsock非阻塞select模式服务器
- Linux网络编程之select
- linux网络编程之select
- C++网络编程之select
- linux 网络编程---->多路复用:select实例!
- 网络编程:select模型的简单实例
- linux 网络编程---->多路复用:select实例!
- Linux 网络编程 select复用模式
- windows网络编程之Winsock(三)非阻塞select模式服务器
- windows网络编程之 (三) - Winsock非阻塞select模式服务器
- Windows网络编程之(二)Socket通信非阻塞模式Select(TCP和UDP)
- 【网络编程】之六、选择select
- 【网络编程】之七、select聊天室
- socket网络编程之select模型
- gcc学习与实践(1)
- gcc学习与实践(2)
- grep工具的使用
- gdb常用命令手册
- c#中override virtual static abstract sealed 的作用
- 网络编程之select 模式开发实例
- linux 下安装Firefox 方法
- C++虚函数、继承等综合使用
- C++继承
- C++命名书写规范
- 关于C++友元
- undefined reference to...异常的解决
- C++结构与类
- Linux下使用Eclipse开发第一个C++程序