任务目标:基于TCP,实现echo服务器和客户端
任务描述:实现echo客户端,即通过命令行输入任何字符串,等回车后发送给服务器。发送的部分要包括换行符。然后等待服务器响应,回送部分的结束也以换行符为标志。当收到换行符结束receive,并打印之。
服务器端程序:收到换行符之后将收到的字符串原样返回给客户端,并包括换行符作为结束
任务要求:
不要动态分配内存;用指针操纵接收的数据,考虑buf有限的问题;考虑客户端和服务器端谁先关闭的问题;尽量形成多个函数。
服务器端
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
#define BUF_SIZE 10 //最大接收数
#define PORT 9190
void RecvMsg(SOCKET);
void SendMsg(SOCKET);
int main(int argc, char* argv[])
{
WSADATA wasdata;
SOCKET ServSock, ClntSock;
char message[BUF_SIZE]; //数据缓冲区
SOCKADDR_IN servAdr, clntAdr;
int strlen, clntAdrSize;
if (WSAStartup(MAKEWORD(2, 2), &wasdata))
{
cout << "加载动态winsock.dll失败!";
exit(1);
}
ServSock = socket(AF_INET, SOCK_STREAM, 0);
if (ServSock == INVALID_SOCKET)
{
cout << "创建套接字失败!";
exit(1);
}
memset(&servAdr, 0, sizeof(servAdr));
servAdr.sin_family = AF_INET;
servAdr.sin_addr.s_addr = htonl(INADDR_ANY);
servAdr.sin_port = htons(PORT);
if (bind(ServSock, (SOCKADDR*)&servAdr, sizeof(servAdr)) == SOCKET_ERROR)
{
cout << "绑定套接字失败! ";
exit(1);
}
if (listen(ServSock, 5) == SOCKET_ERROR)
{
cout << "监听套接字失败!";
exit(1);
}
//cout << "ip: " << inet_ntoa(servAdr.sin_addr) << endl;
clntAdrSize = sizeof(clntAdr);
for (int i = 0; i < 5; i++)
{
ClntSock = accept(ServSock, (SOCKADDR*)&clntAdr, &clntAdrSize);
if (ClntSock == -1)
{
cout << "接收失败!";
exit(1);
}
else
cout << "Connected client......" << i + 1 << endl;
while ((strlen = recv(ClntSock, message, BUF_SIZE - 1, 0)) != 0)
send(ClntSock, message, strlen, 0);
closesocket(ClntSock);
cout << "退出连接" << endl;
}
closesocket(ServSock);
WSACleanup();
return 0;
}
客户端
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <WinSock2.h>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
#define BUF_SIZE 1024
char message[BUF_SIZE];
int SendMsg(SOCKET);
void RecvMsg(SOCKET, int);
int main(int argc, char* argv[])
{
WSADATA wsadata;
SOCKET hSock;
int str_len, recv_len, recv_cnt;
SOCKADDR_IN servAdr;
if (WSAStartup(MAKEWORD(2, 2), &wsadata) != 0)
{
cout << "加载winsock.dll失败!" << endl;
exit(1);
}
hSock = socket(AF_INET, SOCK_STREAM, 0);
if (hSock == INVALID_SOCKET)
{
cout << "创建套接字失败!" << endl;
exit(1);
}
memset(&servAdr, 0, sizeof(servAdr));
servAdr.sin_family = AF_INET;
servAdr.sin_addr.s_addr = inet_addr("192.168.56.1");
servAdr.sin_port = htons(9190);
if (connect(hSock, (SOCKADDR*)&servAdr, sizeof(servAdr)) == SOCKET_ERROR)
{
cout << "连接失败!" << endl;
exit(1);
}
else
cout << "Connected......" << endl;
while (1)
{
memset(message, 0, BUF_SIZE);
fputs("请输入要发送的信息[Q ot quit]:", stdout);
fgets(message, BUF_SIZE, stdin);
if (!strcmp(message, "q\n") || !strcmp(message, "Q\n"))
break;
str_len = SendMsg(hSock);
RecvMsg(hSock, str_len);
cout << "来自服务器端的消息是:" << message << endl;
}
closesocket(hSock);
WSACleanup();
return 0;
}
int SendMsg(SOCKET Sock)
{
SOCKET hSock = Sock;
int str_len;
str_len = send(hSock, message, strlen(message), 0); //传输的数据长度,在echo客户端内已知
return str_len;
}
void RecvMsg(SOCKET Sock, int str_len)
{
SOCKET hSock = Sock;
int recv_len, recv_cnt;
recv_len = 0;
while (recv_len < str_len)
{
recv_cnt = recv(hSock, &message[recv_len], BUF_SIZE - 1, 0);
if (recv_cnt == -1)
cout << "接收失败!" << endl;
recv_len += recv_cnt;
}
message[recv_len] = 0;
}