C++Socket
2016-03-17 17:40
281 查看
Server
Client
#include<Winsock2.h> #include<stdio.h> #include <iostream> #include <string> using namespace std; int main() { //********************************************************** //第一步:加载socket库函数 //********************************************************** //定义一个WORD的变量 WORD wVersionRequested; WSADATA wsaData; int err; //低字节主版本号 高字节副版本号 如下是版本2.1 //(WORD)(1<<8|2) wVersionRequested = MAKEWORD(2,1); //WSAStartup应该与WSACleanup成对使用,WSAStartup的功能是初始化Winsock DLL, //WSACleanup是来解除与Socket库的绑定并且释放Socket库所占用的系统资源 //WSAStartup函数的第一个参数是加载WinSock库的版本,WSAStartup函数的第二个参数中设置使用的WinSock库的版本, //当正确初始化时,WSAStartup会返回0。但我在WSAStartup函数的第一个参数中胡乱设置了一个版本号,WSAStartup仍然会返回0。 //最后经测试发现,如果在WSAStartup函数第一个参数中设置的版本号不存在,那么会自动使用WinSock库中最高版本2.2 err = WSAStartup(wVersionRequested, &wsaData); if (err != 0) { cout << "*******Fail to load Socket!*******" << endl; return 0; } else { cout << "*******Success to load Socket!*******" << endl; } if (LOBYTE(wsaData.wVersion) != 2 ||HIBYTE(wsaData.wVersion) != 1) { cout << "*******版本不是2.1版本*******" << endl; WSACleanup(); return 0; } //********************************************************** //第二步创建套接字 //********************************************************** //af: 一个地址描述。目前仅支持AF_INET格式,也就是说ARPA Internet地址格式。 //type: 指定socket类型。新套接口的类型描述类型,如TCP(SOCK_STREAM)和UDP(SOCK_DGRAM)。 // 常用的socket类型有,SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、SOCK_PACKET、SOCK_SEQPACKET等等。 //protocol:顾名思义,就是指定协议。套接口所用的协议。如调用者不想指定,可用0。常用的协议有,IPPROTO_TCP、IPPROTO_UDP、IPPROTO_STCP、IPPROTO_TIPC等,它们分别对应TCP传输协 // 议、UDP传输协议、STCP传输协议、TIPC传输协议。 SOCKET sockSrv = socket(AF_INET, SOCK_STREAM, 0); //********************************************************** //第三步:绑定套接字 //********************************************************** //获取地址结构 SOCKADDR_IN addrSrv; //typedef struct sockaddr_in { //#if(_WIN32_WINNT < 0x0600) // short sin_family; //#else //(_WIN32_WINNT < 0x0600) // ADDRESS_FAMILY sin_family; //#endif //(_WIN32_WINNT < 0x0600) // USHORT sin_port; // IN_ADDR sin_addr; // CHAR sin_zero[8]; //} SOCKADDR_IN, *PSOCKADDR_IN; //sa_family是地址家族,一般都是“AF_xxx”的形式。通常大多用的是都是AF_INET, 代表TCP / IP协议族。 //sa_data是14字节协议地址。 addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY); //将IP地址指定为INADDR_ANY,允许套接字向任何分配给本地机器的IP地址发送或接收数据 //监听所有发送请求的地址 //htonl()将主机的无符号长整形数转换成网络字节顺序。 //host to network, l 的意思是返回类型是long addrSrv.sin_family = AF_INET; //sin_family 表示地址族,对于IP地址,sin_family成员将一直是AF_INET addrSrv.sin_port = htons(6000); //htons()就是将一个数的高低位互换 高八位与低八位呼唤位置 //htons()将主机的无符号短整形数转换成网络字节顺序 bind(sockSrv, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR)); //int bind(int sockfd, const struct sockaddr * my_addr, socklen_t addrlen); //返回:成功返回0,失败返回 - 1. //参数列表中,sockfd 表示已经建立的socket编号(描述符); //my_addr 是一个指向sockaddr结构体类型的指针; //参数addrlen表示my_addr结构的长度,可以用sizeof函数获得。 listen(sockSrv, 5); //参数一:用于标识一个已捆绑未连接套接口的描述字 //参数二:等待连接队列的最大长度 //监听客户端 //定义从客户端接受的地址信息 SOCKADDR_IN addrClient; int len = sizeof(SOCKADDR); cout << "**********等待客户端的连接**********" << endl; SOCKET sockConn = accept(sockSrv, (SOCKADDR*)&addrClient, &len); //参数一:套接字描述符,该套接口在listen()后监听连接 //指针,指向一缓冲区,其中接收为通讯层所知的连接实体的地址。Addr参数的实际格式由套接口创建时所产生的地址族确定。 //addrlen:(可选)指针,输入参数,配合addr一起使用,指向存有addr地址长度的整型数 //(可选)指针,指向一缓冲区,其中接收为通讯层所知的连接实体的地址。Addr参数的实际格式由套接口创建时所产生的地址族确定。 //addrlen:(可选)指针,输入参数,配合addr一起使用,指向存有addr地址长度的整型数 while (1) { string sendBuf; //sendBuf= "欢迎IP:"+inet_ntoa(addrClient.sin_addr) ; //sprintf(sendBuf, "welcome %s to 济南", inet_ntoa(addrClient.sin_addr)); cout << "来自服务器的信息:"; cin >> sendBuf; send(sockConn, sendBuf.c_str(), strlen(sendBuf.c_str()) + 1, 0); char recvBuf[256]; recv(sockConn, recvBuf, 256, 0); cout << "来自客户端的信息:" << recvBuf << endl;; } closesocket(sockConn); WSACleanup(); return 0; }
Client
#include<Winsock2.h> #include <iostream> #include <string> using namespace std; #pragma comment(lib,"ws2_32.lib") int main() { WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD(1, 1); err = WSAStartup(wVersionRequested, &wsaData); if (err != 0) { return 0; } if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1) { WSACleanup(); return 0; } //********************************************************** //第一步,创建套接字 SOCKET sockClient = socket(AF_INET, SOCK_STREAM, 0); //定义套接字地址 SOCKADDR_IN addrSrv; //获取服务器IP地址,inet_addr()将IP地址转为点分十进制的格式 addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); //sin_family 表示地址族,对于IP地址,sin_family成员将一直是AF_INET addrSrv.sin_family = AF_INET; addrSrv.sin_port = htons(6000); if (connect(sockClient, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR)) != 0) { cout << "与服务器连接失败" << endl;; return 0; } else { cout << "**********连接服务器成功**********" << endl; while (1) { string sendBuf; cout << "来自客户端的信息:"; cin >> sendBuf; send(sockClient, sendBuf.c_str(), strlen(sendBuf.c_str()) + 1, 0); char recvBuf[256]; recv(sockClient, recvBuf, 256, 0); cout << "来自服务器的信息:" << recvBuf << endl; } } //关闭套接字 closesocket(sockClient); //清除套接字资源 WSACleanup(); return 0; }
相关文章推荐
- 在初学C语言容易忽略的函数-scanf()函数与printf()函数
- c++ 之 编译期多态&运行期多态
- KMP字符串匹配算法
- NDK开发之c、c++区别
- c++ 牛人的博客
- C++中的静态类型和动态类型的定义
- C++ virtual关键字理解
- C++ BF模式串匹配算法!
- 八皇后问题C++实现
- C语言类型限定修饰符(十八)const、(*)、
- C++生成的exe,在非开发环境下运行报错
- 对称密钥解密——C++方法
- C++获取时间 场景写日志
- Avl树的基本操作(c语言实现)
- C++怎样把第三方库隐藏在实现下面
- 【C++探索之旅】第二部分第一课:面向对象初探,string的惊天内幕
- 【C++探索之旅】第二部分第一课:面向对象初探,string的惊天内幕
- 使用模板方法模式实现选择题答题 C++
- C++ 之 新式转型操作符
- 基于MFC编写Windows服务程序