1.网络通信,首先计算机网络的基础知识得有,要了解TCP协议等等
2.在一个工程下建立一个新的项目Sever用作服务器,解释全写在代码中:
#include <winsock2.h>
#include <windows.h>
#include <tchar.h>
#include <iostream>
//所有的 Winsock 函数都是从 WS2_32.DLL 导出的,
//V在默认情况下并没有链接到该 库,如果想使用 Winsock API,
//就必须包含下边的库文件。
#pragma comment(lib,"Ws2_32.lib")
using namespace std;
//现在开发网络应用程序都使用 Winsock2
void _tmain()
{
//初始化资源
WSADATA v1; //这是一个结构体
WSAStartup(MAKEWORD(2, 2) /*指定想要加载的 Winsock 库的版本,高字节为次版本号,低字节为主版本号*/ , &v1);
//创建套接字
SOCKET ListenSocket;
//*internetwork: UDP, TCP, etc,地址家族*/
//*这个就是使用TCP协议当然还有UDP协议*/
//这个应该时再次确认协议
ListenSocket = socket(AF_INET,SOCK_STREAM, IPPROTO_TCP);//AF_INET(指IP地址家族),
//SOCK_STREAM 流套接字,使用 TCP 提供有连接的可靠的传输
// IPPROTO_TCP再次用来指定使用的协议类型
if (ListenSocket == INVALID_SOCKET) //就是如果创建失败就是无效的套接字
{
goto Exit;
}
//初始化本地网卡
/*
sockaddr_in结构体
struct sockaddr_in {
short sin_family; // 地址家族(即指定地址格式)应为 AF_INE,它告诉 Winsock 程序使用的是 IP 地址家族
u_short sin_port; // 端口号,最好从2048开始前边为公用的,最大到65 535
struct in_addr sin_addr; // IP 地址
char sin_zero[8]; // 空字节,要设为 0
};
端口号:
*/
sockaddr_in ServerAddress;
ServerAddress.sin_family = AF_INET;
ServerAddress.sin_port = htons(8888); //此处指随便的一个空闲端口号,htons解释如下:
/*
sin_port 字段和 sin_addr 字段分别指定 套接字需要绑定的端口号和 IP 地址。
放入这两个字段的数据的字节顺序必须是网络字节顺序。 因为网络字节顺序和 Intel CPU 的
字节顺序刚好相反,所以必须首先使用 htons 函数进行转换
*/
ServerAddress.sin_addr.S_un.S_addr = INADDR_ANY; // INADDR_ANY,系统会自动使用当前主机配置的所有 IP 地 址
//绑定这个套接字到一个本地地址
if (bind(ListenSocket, (sockaddr*)&ServerAddress, sizeof(sockaddr_in)) == SOCKET_ERROR)
{
goto Exit;
}
//listen 函数设置套接字ListenSocket进入监听状态
listen(ListenSocket, 200);//200是指 监听队列中允许保持的尚未处理的最大连接数量
sockaddr_in ClientAddress = {0};
SOCKET ClientSocket;
int ClientAddressLength = sizeof(sockaddr_in);
CHAR BufferData[0x1000] = { 0 };
//关于下边accept函数的解释
/*
SOCKET accept(
SOCKET s, // 套接字句柄
struct sockaddr* addr, // 一个指向 sockaddr_in 结构的指针,用于取得客户端的地址信息
int* addrlen // 一个指向地址长度的指针 );
该函数在 s 上取出未处理连接中的*****第一个连接*********,然后为这个连接创建新的套接字返回**** 它的句柄。
**********新创建的套接字是处理实际连接的套接字,它
与 s 有相同的属性。 程序默认工作在阻塞模式下,这种方式下如果没有
未处理的连接存在 ,accept 函数会一 直等待下去,直到有新的连接发生才返回。
addrlen 参数用于指定 addr 所指空间的大小,也用于返回地址的实际长度。
如果 addr 或 者 addrlen 是 NULL,则没有关于远程地址的信息返回
*/
//************整个通信的过程是一个动态的交互过程**********
//接收,accept 函数用于接受到来的连接,接受客户端的信息。
//会直接等待直到客户端的启动函数才能执行
ClientSocket = accept(ListenSocket, (sockaddr*)&ClientAddress, &ClientAddressLength);
char *TEXT = "已成功连接服务器!";
//accept函数执行之后会进行send,向其中发送上述内容
send(ClientSocket, TEXT, strlen(TEXT), 0);
//存储,recv 函数从对方接收数据,并将其存储到指定的缓冲区
//当客户端进行输入并才执行recv函数,接收客户端的输入信息
int nrecv=recv(ClientSocket, BufferData/*要收到数据的缓冲区地址*/, 0x1000/*缓冲区的大小*/, 0);
if (nrecv)
{
cout << "收到客户端的信息:" << endl;
cout << endl;
}
printf("%s\r\n", BufferData);//打印
nrecv = 0;
closesocket(ClientSocket);
Exit:
_tprintf(_T("Input AnyKey To Exit\r\n"));
}
3.在工程下再建立一个新的项目Client用作客户端:
#include <winsock2.h>
#include <windows.h>
#include <tchar.h>
#include <iostream>
#pragma comment(lib,"Ws2_32.lib")
using namespace std;
void _tmain()
{
//初始化资源
WSADATA v1;
WSAStartup(MAKEWORD(2, 2), &v1);
//创建套接字
SOCKET ClientSocket; //int a
ClientSocket = socket(AF_INET,SOCK_STREAM, IPPROTO_TCP);
if (ClientSocket == INVALID_SOCKET)
{
goto Exit;
}
//初始化本地网卡
sockaddr_in ServerAddress;
ServerAddress.sin_family = AF_INET;
ServerAddress.sin_port = htons(8888);
ServerAddress.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); // 注意,这里要填写服务器程序(TCPServer 程序)所在机器的 IP 地址 ,这里是本机
CHAR BufferData[0x1000] = { 0 };
//客户端程序在创建套接字之后,要使用 connect 函数请求与服务器连接,服务器那边accept函数才开始执行
connect(ClientSocket, (sockaddr*)&ServerAddress, sizeof(sockaddr_in));
char whatrecv[20];
//服务器的send函数执行后,客户端recv接收信息
int nrecv = recv(ClientSocket,whatrecv,20,0);
if (nrecv)
{
whatrecv[nrecv] = '\0';
cout << whatrecv << endl;
}
cout << "请输入发送到服务器的字符信息:" ;
scanf("%s",BufferData);
int v1 = strlen(BufferData) + 1; //把“/0”的长度也算上
//向服务器发送信息,服务器的recv准备接收
send(ClientSocket, BufferData,v1,0);
closesocket(ClientSocket);
Exit:
_tprintf(_T("Input AnyKey To Exit\r\n"));
}
4.分别右击两个项目名称,进行 重新生成 ,然后在工程的根目录下找到Debug文件夹,找到应用程序(exe)Sever和Client,
先双击Sever,后双击Client,
一定记住这样,下边是运行之后的图片: