网络编程或者说socket 编程其实很简单,我以前在unix下做过,很容易。
但如何在mfc 或者vc 下编程,我却有点犯难,但我看了
https://blog.csdn.net/mowenliunian/article/details/53341402
之后,我觉得一切又变得很简单了。所以我把他的主要内容复制于此。帮助你我编程应用。
一、基于TCP协议的编程步骤
服务器端:
1. 加载套接字库(WSAStartup)
2. 创建用于监听的套接字(socket),然后将其绑定到本地SOCKADDR(bind),并将其设为监听模式(listen)
3. 等待客户请求的到来:一旦收到客户连接请求,返回一个对应该连接的套接字(accept)
4. 利用返回的套接字与客户端进行通信(recv/send)
5. 通信完毕,关闭套接字(closesocket)并终止套接字库的使用(WSACleanup)
-
- WSAData wsaData;
- if(0 != WSAStartup(MAKEWORD(1, 1), &wsaData))
- {
- return;
- }
- if(1 != LOBYTE(wsaData.wVersion) ||
- 1 != HIBYTE(wsaData.wVersion))
- {
-
- WSACleanup();
- return;
- }
-
-
- SOCKET sockListen = socket(AF_INET, SOCK_STREAM, 0);
-
-
- SOCKADDR_IN addrSrv;
- addrSrv.sin_family = AF_INET;
- addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
- addrSrv.sin_port = htons(6000);
- bind(sockListen, (SOCKADDR *)&addrSrv, sizeof(SOCKADDR));
-
-
- listen(sockListen, 6);
-
-
- SOCKADDR_IN addrClient;
- int len = sizeof(SOCKADDR);
- while(1)
- {
-
-
-
- SOCKET sockSrv = accept(sockListen, (SOCKADDR *)&addrClient, &len);
-
-
- char sendBuf[100];
- sprintf(sendBuf, "Welcome %s to http://www.communication.org", inet_ntoa(addrClient.sin_addr));
- send(sockSrv, sendBuf, strlen(sendBuf) + 1, 0);
-
-
- char recvBuf[100];
- recv(sockSrv, recvBuf, sizeof(recvBuf), 0);
- printf("%s\n", recvBuf);
-
-
- closesocket(sockSrv);
- }
-
-
- WSACleanup();
客户端:
1. 加载套接字库(WSAStartup)
2. 创建用于通信的套接字(socket)
3. 向服务器发出连接请求(connect)
4. 利用已连接的套接字与服务器进行通信(send/recv)
5. 通信完毕,关闭套接字(closesocket)并终止套接字库的使用(WSACleanup)
-
- WSADATA wsaData;
- if(0 != WSAStartup(MAKEWORD(1, 1), &wsaData))
- {
- return;
- }
- if (1 != LOBYTE(wsaData.wVersion) ||
- 1 != HIBYTE(wsaData.wVersion))
- {
-
- WSACleanup();
- return;
- }
-
-
- SOCKET sockClient = socket(AF_INET, SOCK_STREAM, 0);
-
-
-
- SOCKADDR_IN addrSrv;
- addrSrv.sin_family = AF_INET;
- addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
- addrSrv.sin_port = htons(6000);
- connect(sockClient, (SOCKADDR *)&addrSrv, sizeof(SOCKADDR));
-
-
- char recvBuf[100];
- recv(sockClient, recvBuf, sizeof(recvBuf), 0);
- printf("%s\n", recvBuf);
-
-
- send(sockClient, "This is TcpClient One.", strlen("This is TcpClient One.")+1, 0);
-
-
- closesocket(sockClient);
- WSACleanup();
二、基于UDP协议的编程步骤
服务器端:
1. 加载套接字库(WSAStartup)
2. 创建用于通信的套接字(socket),然后将其绑定到本地SOCKADDR(bind)
3. 利用创建的套接字与客户端进行通信(recvfrom/sendto)
4. 通信完毕,关闭套接字(closesocket)并终止套接字库的使用(WSACleanup)
-
- WSAData wsaData;
- if(0 != WSAStartup(MAKEWORD(1, 1), &wsaData))
- {
- return;
- }
- if(1 != LOBYTE(wsaData.wVersion) ||
- 1 != HIBYTE(wsaData.wVersion))
- {
-
- WSACleanup();
- return;
- }
-
-
-
- SOCKET sockSrv = socket(AF_INET, SOCK_DGRAM, 0);
-
-
- SOCKADDR_IN addrSrv;
- addrSrv.sin_family = AF_INET;
- addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
- addrSrv.sin_port = htons(6000);
- bind(sockSrv, (SOCKADDR *)&addrSrv, sizeof(SOCKADDR));
-
-
-
- SOCKADDR_IN addrClient;
- int len = sizeof(SOCKADDR);
- char recvBuf[100];
- recvfrom(sockSrv, recvBuf, sizeof(recvBuf), 0,
- (SOCKADDR *)&addrClient, &len);
- printf("%s\n", recvBuf);
-
-
- closesocket(sockSrv);
- WSACleanup();
客户端:
1. 加载套接字库(WSAStartup)
2. 创建用于通信的套接字(socket)
3. 利用创建的套接字与服务器进行通信(sendto/recvfrom)
4. 通信完毕,关闭套接字(closesocket)并终止套接字库的使用(WSACleanup)
-
- WSAData wsaData;
- if(0 != WSAStartup(MAKEWORD(1, 1), &wsaData))
- {
- return;
- }
- if(1 != LOBYTE(wsaData.wVersion) ||
- 1 != HIBYTE(wsaData.wVersion))
- {
-
- WSACleanup();
- return;
- }
-
-
- SOCKET sockClient = socket(AF_INET, SOCK_DGRAM, 0);
-
-
- SOCKADDR_IN addrSrv;
- addrSrv.sin_family = AF_INET;
- addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
- addrSrv.sin_port = htons(6000);
- sendto(sockClient, "Hello", strlen("Hello")+1, 0,
- (SOCKADDR *)&addrSrv, sizeof(SOCKADDR));
-
-
- closesocket(sockClient);
- WSACleanup();
三、注意事项
编写基于socket网络应用程序时,需事先做到两件事:
1. 包含头文件:Winsock2.h
2. 添加依赖项:ws2_32.lib
基于TCP协议网络应用程序和基于UDP协议的网络应用程序的区别在于:
1. TCP服务器需要在接收到客户端连接请求后,才能与之通信;而UDP服务器直接利用绑定到本地的套接字等待接收数据,接收到数据后才知道客户端的地址信息
2. TCP客户端需要在与服务器建立链接后,才能与之通信;而UDP客户端直接利用绑定到本地的套接字向服务器发送数据,指定的服务器地址信息可以任意指定,因此不确定能不能被接收
与unix 或者linux 下的区别主要是调用WSAStartup(MAKEWORD(1, 1), &wsaData) 开始, 结束调用WSACleanup()。
一、WSAStartup函数
int WSAStartup ( WORD wVersionRequested, LPWSADATA lpWSAData );
使用Socket的程序在使用Socket之前必须调用WSAStartup函数。以后应用程序就可以调用所请求的Socket库中的其它Socket函数了。
二、WSACleanup函数
int WSACleanup (void);
应用程序在完成对请求的Socket库的使用后,要调用WSACleanup函数来解除与Socket库的绑定并且释放Socket库所占用的系统资源。
WSAStartup() - 使用方法
当一个应用程序调用WSAStartup函数时,操作系统根据请求的Socket版本来搜索相应的Socket库,然后绑定找到的Socket库到该应用程序中。以后应用程序就可以调用所请求的Socket库中的其它Socket函数了。该函数执行成功后返回0。
例:假如一个程序要使用2.1版本的Socket,那么程序代码如下
wVersionRequested = MAKEWORD( 2, 1 );
err = WSAStartup( wVersionRequested, &wsaData );