网络编程之路---8

来源:互联网 发布:声优聊天软件 编辑:程序博客网 时间:2024/05/01 12:04

设置非阻塞式socket

int ioctlsocket(SOCKET s, long cmd, u_long* argp);

socket句柄 在sockets上面执行的命令 指定cmd命令的参数

服务端(非阻塞):

#include <winsock2.h>#pragma comment(lib, "ws2_32.lib")#include <stdio.h>#define BUF_SIZE 64 //定义缓冲区的大小int main(int argc, char *argv[]){WSADATA wsaData; //WSA windows socket apichar buf[BUF_SIZE]; //缓冲区int resValue; //用来接收函数的返回值if ((WSAStartup(MAKEWORD(2,2), &wsaData)) != 0)//用于初始化windows sockets并返回WSADATA结构体{//MessageBox(NULL, L"无法初始化", L"WindowsApi", 0);printf("无法初始化!");return 0;}//...SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //创建tcp套接字(服务器)//地址家族, 套接字类型,套接字使用的协议if (s == INVALID_SOCKET){printf("socket error!");}int iMode = 1;resValue = ioctlsocket(s, FIONBIO, (u_long FAR*)&iMode);           //将该socket设置为非阻塞式的if (resValue == SOCKET_ERROR){printf("ioctlsocket failed\n");closesocket(s);WSACleanup();return -1;}SOCKADDR_IN addr;           //命名socket,服务器地址//struct sockaddr_in addr; //命名socket,地址addr.sin_family = AF_INET; //因特网地址家族或协议系列addr.sin_port = htons(9990); //主机->网络addr.sin_addr.S_un.S_addr =/*inet_addr("222.18.167.206")*//*htonl(INADDR_ANY)*/inet_addr("222.18.167.240"); //在任意本地地址上进行监听int errorCode; //错误代码int addr_len = sizeof(struct sockaddr_in);errorCode = bind(s, (const SOCKADDR*)&addr, addr_len);//未绑定的套接字描述符 命名socket的地址 地址长度if (errorCode == SOCKET_ERROR){printf("bind error!");closesocket(s);exit(1);}//截止到现在socket的全部属性已经被填充,客户端可以定位到服务器socketerrorCode = listen(s, 3);if (errorCode == SOCKET_ERROR){printf("listen error");closesocket(s); //关闭套接字exit(2);}//服务端的socket已经准备好...//现在开始客户端的socketprintf("TCP SERVER start...\n");SOCKET sockAccept; //执行accept函数后用于实际通信的套接字SOCKADDR_IN ClientAddr; //客户端地址int len = sizeof(ClientAddr);while (true){sockAccept = accept(s, (SOCKADDR*)&ClientAddr, &len);if (sockAccept == INVALID_SOCKET) //为非阻塞式的,所以socket不一定就是有效的{int err = WSAGetLastError();if (err == WSAEWOULDBLOCK){Sleep(100);continue;}else{printf("accept failed\n");closesocket(s);closesocket(sockAccept);WSACleanup();return -1;}}break; }//循环接收来自客户端的数据while (true){ZeroMemory(buf, BUF_SIZE); //每次清空缓冲resValue = recv(sockAccept, buf, BUF_SIZE, 0); //接收来自客户端的数据 现在是非阻塞式的if (resValue == SOCKET_ERROR){int err = WSAGetLastError();if (err == WSAEWOULDBLOCK){Sleep(500);continue;}else if(err == WSAETIMEDOUT || err == WSAENETDOWN) //超时 或者网络关闭{printf("recv failed!");closesocket(s);closesocket(sockAccept);WSACleanup();return -1;}}SYSTEMTIME st;GetLocalTime(&st);char sDataTime[30];sprintf(sDataTime, "%4d-%2d-%2d:%2d:%2d", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute,st.wMinute, st.wSecond);printf("%s, Recv From Client [%s:%d] :%s\n", sDataTime, inet_ntoa(ClientAddr.sin_addr), ClientAddr.sin_port, buf);if (strcmp(buf, "quit") == 0){resValue = send(sockAccept, "quit", strlen("quit"), 0); //发往客户端的数据break;}//向客户端发送回显字符else{char msg[BUF_SIZE];sprintf(msg, "Message Received - %s", buf);resValue = send(sockAccept, buf, BUF_SIZE, 0);if (resValue == SOCKET_ERROR){int err = WSAGetLastError();if (err == WSAEWOULDBLOCK){Sleep(500);continue;}else {printf("Socket send Failed\n");closesocket(s);closesocket(sockAccept);WSACleanup();return -1;}}//break;}}closesocket(s);closesocket(sockAccept);if ((WSACleanup() == SOCKET_ERROR)){MessageBox(NULL, L"清除失败", L"WindowsApi", 0);return 0;}system("pause");return 0;}

客户端(非阻塞)

#include <winsock2.h>#pragma comment(lib, "ws2_32.lib")#include <stdio.h>#include <iostream>#include <string>#define BUF_SIZE 64 //定义缓冲区的大小int main(int argc, char *argv[]){WSADATA wsaData;SOCKET sHost; //创建客户端的socketint resValue; //函数返回值,用于查看函数执行情况char buf[BUF_SIZE]; //缓冲区if ((WSAStartup(MAKEWORD(2,2), &wsaData)) != 0)//用于初始化windows sockets并返回WSADATA结构体{//MessageBox(NULL, L"无法初始化", L"WindowsApi", 0);printf("无法初始化!");return 0;}sHost = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if (sHost == INVALID_SOCKET){printf("socket failed! \n");WSACleanup();return -1;}int iMode = 1; //设置为非阻塞模式resValue = ioctlsocket(sHost, FIONBIO, (u_long FAR*)&iMode);if (resValue == SOCKET_ERROR){printf("ioctlsocket error\n");closesocket(sHost);WSACleanup();return -1;}SOCKADDR_IN servAddr; //服务器的地址,端口号servAddr.sin_family = AF_INET;servAddr.sin_addr.S_un.S_addr = inet_addr("222.18.167.240");servAddr.sin_port = htons(9990);int sServerAddlen = sizeof(servAddr); //服务器地址长度while (true){resValue = connect(sHost, (const SOCKADDR*)&servAddr, sServerAddlen);if (resValue == SOCKET_ERROR){int err = WSAGetLastError();if (err == WSAEWOULDBLOCK) //非阻塞 还未有socket连接{Sleep(500);continue;}else if (err == WSAEISCONN) //已经建立连接 WSAEWOULDBLOCK WSAEINVAL监听 WSAEISCONN 如果第一次成功就会直接进入{break;}else{printf("connect failed\n");closesocket(sHost);WSACleanup();return -1;}}}while (true){printf("\nplease input a string to send\n");std::string str;std::getline(std::cin, str); //接收输入的数据ZeroMemory(buf,BUF_SIZE);strcpy(buf, str.c_str()); //将用户的输入复制到buf里面while (true){resValue = send(sHost, buf, strlen(buf), 0);if (resValue == SOCKET_ERROR){int err = WSAGetLastError();if (err == WSAEWOULDBLOCK){Sleep(500);continue;}else {printf("socket send failed!\n");closesocket(sHost);WSACleanup();return -1;}}break;}while (true){ZeroMemory(buf,BUF_SIZE);resValue = recv(sHost, buf, sizeof(buf) + 1, 0);if (resValue == SOCKET_ERROR){int err = WSAGetLastError();if (err == WSAEWOULDBLOCK){Sleep(500);continue;}else if(err == WSAETIMEDOUT || err == WSAENETDOWN){printf("recv failed\n");closesocket(sHost);WSACleanup();return -1;}break;}break;}// resValue = recv(sHost, buf, sizeof(buf) + 1, 0);// //要接收数据的socket 要接收数据buf的地址 要接收数据buf的长度 0// if (resValue == SOCKET_ERROR)// {// printf("socket receive failed!\n");// closesocket(sHost);// WSACleanup();// return -1;// }printf("Receive from server: %s", buf);if (strcmp(buf, "quit") == 0){printf("quit");break;}}closesocket(sHost);WSACleanup();system("pause");return 0;}


0 0