简单网络通信

  • 服务器端
  • 客户端
  • 运行实例



通讯建立后首先由服务器端发送消息,客户端接收消息;


接着客户端发送消息,服务器端接收消息,实现交互发送消息。


服务器端或客户端有一方发送"end"即终止通信。

服务器端

#include<iostream>
#include<winsock2.h>
#define PORT 65432 //定义端口号常量
#pragma comment(lib,"ws2_32.lib")
using namespace std;
int main()
{
	SOCKET sock_server, newsock;
	struct sockaddr_in addr;
	struct sockaddr_in client_addr;
	char msgbuffer[1000];//字符缓冲区
	//初始化winsock2.DLL
	WSADATA wsaData;
	WORD wVersionRequested = MAKEWORD(2, 2);
	if (WSAStartup(wVersionRequested,&wsaData)!=0)
	{
		cout << "加载winsock.dll失败!" << endl;
		return 0;
	}
	//创建套接字
	if ((sock_server=socket(AF_INET,SOCK_STREAM,0))==SOCKET_ERROR)
	{
		cout << "创建套接字失败!错误代码:" << WSAGetLastError() << endl;
		WSACleanup();
		return 0;
	}
	//填写要绑定的本地地址
	int addr_len = sizeof(struct sockaddr_in);
	memset((void*)&addr, 0, addr_len);//将地址结构变量清0
	addr.sin_family = AF_INET;
	addr.sin_port = htons(PORT);
	addr.sin_addr.s_addr = htonl(INADDR_ANY);//允许使用本机的任何IP地址
	//给监听套接字绑定地址
	if (bind(sock_server,(struct sockaddr*)&addr,sizeof(addr))!=0)
	{
		cout<<"地址绑定失败!错误代码:" << WSAGetLastError() << endl;
		closesocket(sock_server);
		WSACleanup();
		return 0;
	}
	//将套接字设为监听状态
	if (listen(sock_server, 0) != 0)
	{
		cout << "listen函数调用失败!错误代码:" << WSAGetLastError() << endl;
		closesocket(sock_server);
		WSACleanup();
		return 0;
	}
	else cout << "listenning......" << endl;
	//接受连接请求
	if ((newsock = accept(sock_server, (struct sockaddr*)&client_addr,
		&addr_len)) == INVALID_SOCKET)
	{
		cout << "accept函数调用失败!错误代码:" << WSAGetLastError() << endl;
		return 0;
	}
	else cout << "成功接收一个连接请求!" << endl;
	//成功接受一个连接后先发送信息,再接收信息
	int size;
	//实现交互部分
	while (1)
	{
		cout<<"服务器发送数据:"<<endl;
		cin.getline(msgbuffer,sizeof(msgbuffer));
		if (strcmp(msgbuffer,"end\0")==0)
		{
			cout<<"关闭连接!"<<endl;
			break;
		}
		size = send(newsock, msgbuffer, sizeof(msgbuffer), 0);//给客户端发送一段信息
		if (size == SOCKET_ERROR)
		{
			cout << "发送信息失败!错误代码:" << WSAGetLastError() << endl;
			break;
		}
		else if (size == 0)
		{
			cout << "对方已关闭连接" << endl;
			break;
		}
		else cout << "信息发送成功!" << endl;
		size = recv(newsock, msgbuffer, sizeof(msgbuffer), 0);//接收信息
		if (size == SOCKET_ERROR)
		{
			cout << "接收信息失败!错误代码:" << WSAGetLastError() << endl;
			break;
		}
		else if (size == 0)
		{
			cout << "对方已关闭连接" << endl;
			break;
		}
		else cout << "The message from Client:" << msgbuffer << endl;
	}
	//结束处理
	closesocket(newsock);//通信完毕关闭已连接套接字
	closesocket(sock_server);//关闭监听套接字
	WSACleanup();//注销winSock动态链接库
	return 0;
}

客户端

#include<iostream>
#include<cstdio>
#include<winsock2.h>
#define PORT 65432 //定义要访问的服务器端口常量
#pragma comment(lib,"ws2_32.lib")
using namespace std;
int main()
{
	//定义相关变量
	int sock_client;
	struct sockaddr_in server_addr;
	int addr_len = sizeof(struct sockaddr_in);
	char msgbuffer[1000];//字符缓冲区
	//初始化winsock2.DLL
	WSADATA wsaData;
	WORD wVersionRequested = MAKEWORD(2, 2);
	if (WSAStartup(wVersionRequested, &wsaData) != 0)
	{
		cout << "加载winsock.dll失败!" << endl;
		return 0;
	}
	//创建套接字
	if ((sock_client = socket(AF_INET, SOCK_STREAM, 0)) == SOCKET_ERROR)
	{
		cout << "创建套接字失败!错误代码:" << WSAGetLastError() << endl;
		WSACleanup();
		return 0;
	}
	//填写服务器地址
	char IP[20];
	cout << "请输入服务器IP地址:";
	cin >> IP;
	memset((void*)&server_addr, 0, addr_len);//将地址结构变量清0
	//ZeroMemory((void*)&server_addr, sizeof(server_addr));
	server_addr.sin_family = AF_INET;
	server_addr.sin_port = htons(PORT);
	server_addr.sin_addr.s_addr = inet_addr(IP);
	//与服务器建立连接
	if (connect(sock_client, (struct sockaddr*)&server_addr, addr_len) != 0)
	{
		cout << "连接失败!错误代码:" << WSAGetLastError() << endl;
		closesocket(sock_client);
		WSACleanup();
		return 0;
	}
	else cout << "连接成功,等待服务器发送数据:" << endl;
	//实现交互部分
	int size;
	getchar();//用于接收缓冲区中的'\n'
	while (1)
	{
		size = recv(sock_client, msgbuffer, sizeof(msgbuffer), 0);//接收消息
		if (strcmp(msgbuffer, "end\0") == 0)
		{
			cout << "关闭连接!" << endl;
			break;
		}
		if (size < 0)
		{
			cout << "接收信息失败!错误代码:" << WSAGetLastError() << endl;
			break;
		}
		else if (size == 0)
		{
			cout << "对方已经关闭连接" << endl;
			break;
		}
		else cout << "The message from Server:" << msgbuffer << endl;
		//从键盘输入一行文字发送给服务器
		cout << "从键盘输入发给服务器的信息:" << endl;
		cin.getline(msgbuffer, sizeof(msgbuffer));
		if (strcmp(msgbuffer, "end\0") == 0)
		{
			cout << "关闭连接!" << endl;
			break;
		}
		size = send(sock_client, msgbuffer, sizeof(msgbuffer), 0);
		if (size<0)
		{
			cout << "发送信息失败!错误代码:" << WSAGetLastError() << endl;
			break;
		}
		else if (size == 0)
		{
			cout << "对方已关闭连接!" << endl;
			break;
		}
		else cout << "信息发送成功!" << endl;
	}
	//结束处理
	closesocket(sock_client);
	WSACleanup();
	return 0;
}

使用getline()函数可以输入带有空格的字符串,服务器端的getchar()函数用于清除输入IP地址后留在缓冲区中的’\n’。
注意:字符缓冲区大小的设置,接收端可以比发送端大但不可以小于发送端,否则会产生溢出。

运行实例

android tcp客户端发送发送大量数据导致客户端收数据丢失 tcp服务器给客户端发消息_socket