1 #include<winsock2.h>//winsock的头文件
2 #include<iostream>
3 using namespace std;
4
5 //指定动态库的lib文件
6 #pragma comment(lib,"ws2_32.lib")
7
8 //TCP服务端
9 int main()
10 {
11
12 //初始化winsock2.2相关的动态库
13 WSADATA wd;//获取socket相关信息
14 if (WSAStartup(MAKEWORD(2, 2), &wd) != 0)//0表示成功
15 {
16 cout << "WSAStartup error:"<< WSAGetLastError() << endl;
17 return 0;
18 }
19
20 //1.创建TCP socket , 流式套接字
21 SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
22 if (s == INVALID_SOCKET)
23 {
24 cout << "socket error:" << WSAGetLastError() << endl;
25 return 0;
26 }
27
28 //2.绑定socket到一个IP地址和端口
29 sockaddr_in addr;//不建议使用sockaddr,建议用sockaddr_in
30 addr.sin_port = htons(8000);//网络字节序
31 addr.sin_addr.S_un.S_addr =inet_addr( "127.0.0.1" );//网络字节序
32 addr.sin_family = AF_INET; //地址族
33 int len = sizeof(sockaddr_in);
34 if (bind(s, (sockaddr *)&addr, len) == SOCKET_ERROR)
35 {
36 cout << "bind error:" << WSAGetLastError() << endl;
37 return 0;
38 }
39
40 //3.监听, 5代表正在等待完成相应的TCP三路握手过程的队列长度
41 if(listen(s, 5) == SOCKET_ERROR)
42 {
43 cout << "listen error:" << WSAGetLastError() << endl;
44 return 0;
45 }
46
47
48 //4.接受客户端请求,并且返回和客户端通讯的套接字
49 sockaddr_in addrClient;// 保存客户端IP地址端口
50 memset(&addrClient, 0, sizeof(sockaddr_in));
51 len = sizeof(sockaddr_in);
52 SOCKET c= accept(s, (sockaddr*)&addrClient, &len);//成功返回套接字
53 if (c == INVALID_SOCKET)
54 {
55 cout << "accept error:" << WSAGetLastError() << endl;
56 return 0;
57 }
58
59
60 //5.发送,接受消息
61 int ret = 0;
62 do
63 {
64 //向客户端发送数据,不能用监听套接字s,而应该用accept返回的套接字c
65 ret = send(c, "I am Server!", strlen("I am Server!"), 0);//把flag置0
66
67 //接受客户端的消息
68 char buf[64] = {'\0'};
69 ret = recv(c, buf, 64, 0);//把flag置0
70 cout << "recv" << inet_ntoa ( addrClient.sin_addr )<<": "<< buf << endl;// inet_ntoa转换为IP字符串
71 } while (ret != SOCKET_ERROR && ret != 0);//对方关闭,返回0 ,错误返回SOCKET_ERROR
72
73
74 //6.关闭套接字
75 closesocket(s);
76
77
78 //清理winsock环境
79 WSACleanup();
80
81
82 return 0;
83 }