实验名称:基于UDP的编程
实验目的
熟练掌握UDP下的网络编程
实验要求:
熟练掌握UDP下的网络编程,实现相应功能
实验内容:
- 根据课堂所讲的内容,将TCP的登陆系统修改成UDP的登陆系统。
- 1、将老师给的TCP的登陆系统解压编译运行,熟悉系统操作。
- 2、 TCP的登陆系统服务器代码进行修改,修改完成后并运行,用老师给的UDP客户端程序”udp_client.exe”测试它,是否能正常运行。如不行则修改,直到可以为止。
- 3、 对TCP的登陆系统客户端代码进行修改,修改完成后并运行整个系统。
实验结果:
实验代码
- 客户端
// client.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
bool InitSock()
{
WSADATA wsaData;
long iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0)
{
return false;
}
return true;
}
SOCKET CreateTCPSocket() //返回真则成功
{
SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (s == INVALID_SOCKET)
{
WSACleanup();
}
return s;
}
bool Connect(SOCKET s,char *ip,int port)
{
struct sockaddr_in hints;
hints.sin_family = AF_INET;
hints.sin_port = htons(port);
hints.sin_addr.S_un.S_addr=inet_addr(ip);
int r=connect(s,(struct sockaddr FAR* )&hints,sizeof(hints));
if(r!=0)
{
r=WSAGetLastError();
if(r==WSAEWOULDBLOCK)
{
printf("%d block\n",r);
r=WSAGetLastError();
return true;
}
return false;
}
return true;
}
int main(int argc, char* argv[])
{
if(!InitSock())
{
printf("初始化失败!\n");
return 0;
}
SOCKET s= CreateTCPSocket() ;
// unsigned long mode=1;
// ioctlsocket(s,FIONBIO,&mode);
char ip[50]={0};
int port=0;
printf("输入服务器ip地址\n");
scanf("%s",ip);
printf("输入服务器端口号(1024-65535)\n");
scanf("%d",&port);
bool r=Connect(s,ip,port);
if(!r)
{
printf("连接服务器失败!\n");
closesocket(s);
WSACleanup();
return 0;
}
char user[50]={0};
char pass[50]={0};
printf("请输入用户\n");
scanf("%s",user);
printf("请输入密码\n");
scanf("%s",pass);
printf("请选择功能\n");
printf("1 注册\n");
printf("2 登陆\n");
char buf[100]={0};
int n=0;
scanf("%d",&n);
if(n==1)
{
buf[0]=1;
}
else
{
buf[0]=2;
}
strcpy(buf+2,user);
strcpy(buf+50,pass);
int len=send(s,buf,100,0);
if(len!=100)
{
printf("发送失败!\n");
closesocket(s);;
WSACleanup();
return 0;
}
memset((void *)buf,0,100);
aecv:
len=recv(s,buf,100,0);
if(len>0)
{
if(buf[0]==1)
{
if(n==1)
printf("注册成功!\n");
else
printf("登陆成功!\n");
}
else
printf("登陆成功!\n");
}
else
{
printf("接收数据失败!\n");
}
getchar();
closesocket(s);;
WSACleanup();
return 0;
}
服务器端
//服务器端
#include "stdafx.h"
#include <time.h>
#include <iostream>
#include <fstream>
#include <string> // 包含string头文件
using namespace std; // 使用std命名空间
bool InitSock()
{
WSADATA wsaData;
long iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0)
{
return false;
}
return true;
}
SOCKET CreateTCPSocket() // 返回真则成功
{
SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (s == INVALID_SOCKET)
{
WSACleanup();
}
return s;
}
char* GetTime()
{
time_t t = time(NULL);
return ctime(&t);
}
bool Bind(SOCKET s, char* Ip, int port)
{
struct sockaddr_in hints;
hints.sin_family = AF_INET;
hints.sin_port = htons(port);
hints.sin_addr.S_un.S_addr = inet_addr(Ip);
int r = bind(s, (const sockaddr*)&hints, sizeof(hints));
if (r == 0)
return true;
return false;
}
int GetAllIp(char ip[10][50])
{
char name[200];
int r = gethostname(name, 200);
int i = 0;
if (r == 0)
{
LPHOSTENT p = gethostbyname(name);
for (i = 0; p->h_addr_list[i] != 0; i++)
{
strcpy(ip[i], inet_ntoa(*(struct in_addr*)p->h_addr_list[i]));
}
}
return i;
}
void WriteUser(char* user, char* pass)
{
std::ofstream file("user.ini", std::ios::app);
if (file)
{
file << user << " " << pass << std::endl;
file.close();
}
}
bool ReadUser(char* user, char* pass)
{
std::ifstream file("user.ini");
if (file)
{
std::string line;
while (getline(file, line))
{
size_t pos = line.find(' ');
std::string username = line.substr(0, pos);
std::string password = line.substr(pos + 1);
if (username == user)
{
strcpy(pass, password.c_str());
file.close();
return true;
}
}
file.close();
}
return false;
}
int main(int argc, char* argv[])
{
char ip[10][50];
if (InitSock())
{
int i = GetAllIp(ip);
if (i > 0)
{
printf("本机所有的ip地址:\n");
for (int j = 0; j < i; j++)
printf("%d %s\n", j, ip[j]);
printf("请现在服务器ip地址(输入序号):\n");
scanf("%d", &i);
printf("请输入端口号(1024-65535):\n");
int port;
scanf("%d", &port);
if (port < 1024 || port >= 65535)
{
printf("输入端口号错误!");
return 0;
}
SOCKET s = CreateTCPSocket();
int r = Bind(s, ip[i], port);
listen(s, 5);
struct sockaddr_in addr;
int len = sizeof(addr);
while (1)
{
char buf[100] = {0};
SOCKET news = accept(s, (sockaddr*)&addr, &len);
memset((void*)buf, 0, 100);
int i = recv(news, buf, 100, 0);
if (i != 100)
{
printf("接收数据错误!\n");
}
char* user = buf + 1;
char* pass = buf + 50;
unsigned char cmd = buf[0];
if (cmd == 1)
{
// 注册
char pass1[50] = {0};
if (!ReadUser(user, pass1))
{
WriteUser(user, pass);
int n = 1;
buf[0] = 1;
printf("注册: %s 成功 来自于:%s 时间:%s\n", user, inet_ntoa(*(struct in_addr*)&(addr.sin_addr.S_un.S_addr)), GetTime());
send(news, (char*)&n, sizeof(int), 0);
}
else
{
int n = 0;
printf("注册: %s 失败,用户已存在 来自于:%s 时间:%s\n", user, inet_ntoa(*(struct in_addr*)&(addr.sin_addr.S_un.S_addr)), GetTime());
send(news, (char*)&n, sizeof(int), 0);
}
}
else if (cmd == 2)
{
// 登录
char pass1[50] = {0};
if (ReadUser(user, pass1))
{
if (strcmp(pass1, pass) == 0)
{
int n = 2;
printf("登录: %s 成功 来自于:%s 时间:%s\n", user, inet_ntoa(*(struct in_addr*)&(addr.sin_addr.S_un.S_addr)), GetTime());
send(news, (char*)&n, sizeof(int), 0);
}
else
{
int n = 0;
printf("登录: %s 失败,密码错误 来自于:%s 时间:%s\n", user, inet_ntoa(*(struct in_addr*)&(addr.sin_addr.S_un.S_addr)), GetTime());
send(news, (char*)&n, sizeof(int), 0);
}
}
else
{
int n = 0;
printf("登录: %s 失败,用户不存在 来自于:%s 时间:%s\n", user, inet_ntoa(*(struct in_addr*)&(addr.sin_addr.S_un.S_addr)), GetTime());
send(news, (char*)&n, sizeof(int), 0);
}
}
closesocket(news);
}
}
}
return 0;
}
实验心得:
在整个实验过程中,我深刻体会到了TCP和UDP在网络编程中的不同之处。UDP是无连接的、不可靠的传输协议,而TCP是面向连接、可靠的传输协议。在修改登录系统时,我需要注意UDP的特点,保证信息能够正确地传输,并及时处理丢包、重复包等问题。
此外,实验还提醒我重要的网络编程原则,例如错误处理、异常情况处理、数据完整性保证等。在实验过程中,我不断地学习和掌握这些原则,并将其应用到实际的代码中。
总的来说,通过这个实验,我对UDP的网络编程有了更深入的理解,并且掌握了相应的技能。我相信这对我今后的网络编程工作和学习都将有着积极的影响。