客户端
//建立线程
DWORD WINAPI ConnectThreadFunc(LPVOID pParam) {
//初始化
WSAData wsData;
if (!AfxSocketInit(&wsData))
{
AfxMessageBox(_T("Socket 库初始化出错!"));
return false;
}
CMFCApplication1View *pChatClient = (CMFCApplication1View*)pParam;
ASSERT(pChatClient != NULL);
//新建一个socket
pChatClient->ConnectSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (INVALID_SOCKET==pChatClient->ConnectSock ) {
AfxMessageBox(_T("创建socket失败!"));
return FALSE;
}
AfxMessageBox(_T("成功创建socket"));
//获取端口
CString ServeIp;
pChatClient->GetDlgItemText(IDC_SERVEID_INPUT, ServeIp); //取服务端的IP地址
int SPort = pChatClient->GetDlgItemInt(IDC_SERVEPORT_INPUT); //获取端口
if (SPort <= 0 || SPort > 65535) {
AfxMessageBox(_T("请输入合法的端口:1-65535"));
goto _End;
}
AfxMessageBox(_T("端口合法"));
//将IP转换
char AddrIp[16] = { 0 }; //窄字节
USES_CONVERSION;
strcpy_s(AddrIp, 16, T2A(ServeIp)); // T2A:宏,进行字符串的转换
//将服务器的信息放入通用套接字中
sockaddr_in server;
server.sin_family = AF_INET;
server.sin_port = htons(SPort);
server.sin_addr.s_addr = inet_addr("192.168.73.1");
//客户端连接服务端
//将server传给connect
if ( SOCKET_ERROR == connect(pChatClient->ConnectSock, (struct sockaddr*)&server, sizeof(struct sockaddrr*)) ) {
/* char ErrorInfo[256] = { 0 }; //创建数组存储错误信息
sprintf_s(ErrorInfo, "Creat Faile : %d", GetLastError()); //把错误信息写入数组
AfxMessageBox((CString)ErrorInfo);
*/
AfxMessageBox(_T("连接失败!"));
goto _End;
}
pChatClient->MsgShow(_T("服务器连接成功!"));
while (TRUE) {
if (SOCKERT_Select(pChatClient->ConnectSock,100,TRUE)) {
char szBuf[MAX_BUF_SIZE] = { '0' }; //缓冲区
int iRet = recv(pChatClient->ConnectSock, szBuf, MAX_BUF_SIZE, 0);
//recv()用来接收远程主机通过套接字sockfd发送来的数据,
//并把这些数据保存到数组buf中
if (iRet > 0) {
pChatClient->MsgShow((CString)szBuf);
}
else {
pChatClient->MsgShow(_T("连接异常,请重新连接!"));
break;
}
}
Sleep(100);
}
_End:
closesocket(pChatClient->ConnectSock);
return TRUE;
}
服务端
SOCKET ComSock; //用于发送消息
//查看客户端是否发来消息,并快速返回
BOOL SOCKERT_Select(SOCKET Socket, int TimeOut, BOOL bRead) {
fd_set fdset; //通知执行了select()的进程哪一socket或文件发生了可读或可写事件
//long类型的数组,每一个数组元素都能与一打开的文件句柄建立联系
timeval tv; //判断是否超时,用于select()函数
FD_ZERO(&fdset); //清空集合中所有的元素
FD_SET(Socket, &fdset); //设置hSocket,使集合包含hSocket,即建立联系
TimeOut = TimeOut > 1000 ? 1000 : TimeOut;
tv.tv_sec = 0; //秒数
tv.tv_usec = TimeOut; //微秒数
int iRet = 0;
if (bRead) {
//select()测试指定的fd可读?可写?有异常条件待处理? //即对socket操作
iRet = select(0, &fdset, NULL, NULL, &tv);
} //读
else {
iRet = select(0, NULL, &fdset, NULL, &tv);
} //写
if (iRet <= 0) { //返回错误时
return FALSE;
}
else if (FD_ISSET(Socket, &fdset)) {//返回处于就绪状态并且已经包含在fd_set结构中的描述字总数
return TRUE;
}
return FALSE; //返回零时(超时返回零)
}
//通过线程来开启服务器,因为accept是阻塞的
//线程函数
DWORD WINAPI LisenThreadFunc(LPVOID pParam) {
//LPVOID :32位的无类型的指针,在使用的时候再强制转换成需要的类型
CMFCApplication1View *pChatClient = (CMFCApplication1View*)pParam; //强制转换
ASSERT(pChatClient != NULL); //保证指针不为空 //断言函数,表达式为假则退出程序,为真继续执行
//用socket函数创建一个socket,用于监听
//成功则返回一个socket
pChatClient->ListenSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (pChatClient->ListenSock == INVALID_SOCKET) {
AfxMessageBox(_T("创建socket失败!"));
return 0;
}
//绑定,将 ListenSock 绑定在本地的一个ip和端口上
//1、动态获取用户输入的端口
int Port = pChatClient->GetDlgItemInt(IDC_LISTENPORT_INPUT);
if (Port <= 0 || Port > 65535) {
AfxMessageBox(_T("请输入合适的端口:1-65535"));
goto _End;
}
//2、建立通用套接字
sockaddr_in service; //一种通用的套接字地址。用来建立所需信息,最后使用类型转换
//一般用于bind、connect、recvfrom、sendto等函数的参数
service.sin_family = AF_INET; //协议族
service.sin_addr.s_addr = inet_addr("127.0.0.1"); //获取本机所有可能得到的ip地址
service.sin_port = htons(Port); //传递端口 //htons:将主机字节顺序转换为网络字节顺序
//3、利用bind进行绑定
if (bind(pChatClient->ListenSock, (sockaddr*)&service, sizeof(sockaddr_in)) == SOCKET_ERROR) {
AfxMessageBox(_T("绑定失败!"));
goto _End;
}
AfxMessageBox(_T("绑定成功!"));
//监听
if (listen(pChatClient->ListenSock, 4) == SOCKET_ERROR) {
AfxMessageBox(_T("监听失败!"));
goto _End;
}
//服务器已搭建完毕,开始进行消息监测
while (TRUE) {
if (SOCKERT_Select(pChatClient->ListenSock, 1000, TRUE)) {//若有消息
sockaddr_in ClientSocket;
int len = sizeof(sockaddr_in);
//返回客户端(即对方)的IP地址和端口
SOCKET ComSock = accept(pChatClient->ListenSock, (struct sockaddr*)&ClientSocket, &len);
if (ComSock == INVALID_SOCKET) { //若没有收到信息
continue;
}
//当要进行信息交互时,再建一个新线程来进行信息交互
// CMFCApplication1View *ClientCopy;
HANDLE iTtem;
iTtem = CreateThread(NULL, 0, ClientThreadProc, pChatClient, CREATE_SUSPENDED, NULL);
pChatClient->comThread = iTtem;
ResumeThread(iTtem); //恢复线程的执行
}
Sleep(100);
}
_End:
closesocket(pChatClient->ListenSock); //强制关闭socket
return TRUE;
}
由于最近刚学socket,实在不知道怎么改了,请各位大神帮我康康,谢谢大家!(呜呜呜我是新手么的c币)