服务端:
#include "iostream.h"
#include "winsock2.h"#pragma comment (lib,"ws2_32.lib")
#define DEFAULT_PORT 4000 //默认端口号
void WINAPI SendOut();
char info[255]; //服务器端控制台输入字符串
//是否有客户端连接
fd_set fds;
SOCKET sServSock;
int main()
{
WORD wVersionRequested=MAKEWORD(2,2); //初始化Winsock
WSADATA wsaData;
WSAStartup(wVersionRequested,&wsaData); //加载winsock库
sServSock=socket(AF_INET,SOCK_STREAM,0);
sockaddr_in addr;
int nSockErr;
SOCKET sClient;
sockaddr ConnAddr;
int nAddrLen=sizeof(sockaddr);
addr.sin_family=AF_INET;
addr.sin_port=htons(DEFAULT_PORT);
addr.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
//绑定套接字到一个已知地址
if(bind(sServSock,(LPSOCKADDR)&addr,sizeof(addr))==SOCKET_ERROR)
nSockErr=WSAGetLastError();
FD_ZERO(&fds);/*&*/
FD_SET(sServSock,&fds);/*&*/
//将套接字置入监听模式
if (listen(sServSock,5)==SOCKET_ERROR)
nSockErr=WSAGetLastError();
cout << "*****************Wait Client to Connect**********************" << endl;
/*&*/
bool bRunning=true;
do {
fd_set readfds;
CopyMemory(&readfds,&fds,sizeof(fd_set));
if(select(0,&readfds,NULL,NULL,NULL)>0)
{
for(int i=readfds.fd_count-1;i>=0;i--)/* 顺序处理每一个有事件发生的套接字*/
if(readfds.fd_array[i]==sServSock)
{
sClient=accept(sServSock,&ConnAddr,&nAddrLen);
if(sClient==INVALID_SOCKET){
bRunning=false;
break;}
cout<<"One of the Clients Accept Successful"<<endl;
FD_SET(sClient,&fds); /* 将与新客户端对应的套接字加入select函数监视的集合*/
CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)SendOut,NULL,0,NULL);//发送数据
}
else // 与客户端对应的套接字有事件发生说明有数据需要接收
{
char in[255];
SOCKET sClient=readfds.fd_array[i];
if(recv(sClient,in,255,0)!=SOCKET_ERROR)
cout<<"\b<"<<in<<endl<<">";
else{
cout<<"\b<"<<"client exit"<<endl<<">";
FD_CLR(sClient,&fds);// 将该套接字移出select函数监视的集合
closesocket(sClient);}
}
}
} while(bRunning);
WSACleanup();
/*&*/
return 0;
}
//服务器发送函数
void WINAPI SendOut()
{
do {
cin.getline(info,255);
if(!strcmp(info,"bye")) break;
cout<<">";
for(int i=fds.fd_count-1;i>=0;i--)
if( fds. fd_array [i]!=sServSock)
{
fd_set writefds;
FD_ZERO (&writefds);
FD_SET(fds.fd_array[i],&writefds);
if(select(0,NULL,&writefds,NULL,NULL)>0)
send(fds.fd_array[i],info,255,0);
}
} while(true);
closesocket(sServSock);
}
客户端:
#include "iostream.h"
#include "winsock2.h"
#define DEFAULT_PORT 4000 //默认端口号
DWORD WINAPI ThreadFunc(LPVOID pParam); //客户端socket接收线程函数
char info[255]; //控制台输入字符串
void main()
{
WORD wVersionRequested=MAKEWORD(2,2); //初始化Winsock
WSADATA wsaData;
WSAStartup(wVersionRequested,&wsaData); //加载winsock库
SOCKET sClntSock;
sockaddr_in addr;
sockaddr_in ServAddr;
int nSockErr;
// sClntSock=socket(AF_INET,SOCK_DGRAM,0);
sClntSock=socket(AF_INET,SOCK_STREAM,0);
addr.sin_family=AF_INET;
addr.sin_port=0;
addr.sin_addr.s_addr=htonl(INADDR_ANY);
//绑定套接字到一个已知地址
if(bind(sClntSock,(LPSOCKADDR)&addr,sizeof(addr))==SOCKET_ERROR)
nSockErr=WSAGetLastError();
ServAddr.sin_family=AF_INET;
ServAddr.sin_port=htons(DEFAULT_PORT);
cout<<"Please input the ip of server:";
char add_ip[50];
cin>>add_ip;
char dummy;
cin.get(dummy);
ServAddr.sin_addr.s_addr=inet_addr(add_ip);
//连接服务器
if(connect(sClntSock,(const sockaddr*)(&ServAddr),sizeof(ServAddr))==SOCKET_ERROR)
{
nSockErr=WSAGetLastError();
}
else cout<<"*****************Connect successful.****************"<<endl;
//创建socket接收线程
CreateThread(NULL,0,ThreadFunc,&sClntSock,0,NULL);
//接收控制台输入并作相应操作
cout << ">";
cin.getline(info,255);
while(strcmp(info,"bye")){
send(sClntSock,info,255,0);
cout << ">";
cin.getline(info,255);
}
}
//线程函数,接收网络消息
DWORD WINAPI ThreadFunc(LPVOID pParam)
{
SOCKET *s=(SOCKET *)pParam;
char in[255];
while(strcmp(info,"bye")) //退出
{
if(recv(*s,in,255,0)!=SOCKET_ERROR) //接收消息
{
cout << "\b" << in << endl << ">";
cout.flush();
}
else //出错,可能服务器死机
{
cout<<"*****************Server Down*****************"<<endl;
exit(0);
}
}
return 0;
}