ai-zjhcc计算机网路课程设计
、.~① 我们‖打〈败〉了敌人。②我们‖〔把敌人〕打〈败〉了。中南林业科技大学 计算机与信息工程学院计算机网络课程设计报告局域网聊天 ,班级:08通信2班 学号:20082
、
.~
① 我们‖打〈败〉了敌人。
②我们‖〔把敌人〕打〈败〉了。
中南林业科技大学 计算机与信息工程学院
计算机网络课程设计报告
局
域
网
聊
天
,班级:08通信2班 学号:20082226
一. 设计的目的和意义
1. 在学习理论的同时,加强动手能力
2. 学习并掌握网络编程
3. 实际应用计算机网络知识
意义:对以后的毕业设计打下基础,锻炼个人的学习和查阅资料的能力以及对课外相关本专业知识的了解。
二. 设计的理论基础
a.TCP/IP协议概述
TCP/IP 实际上一个一起工作的通信家族,为网际数据通信提供通路。为讨论方便可将
TCP/IP 协议组大体上分为三部分:
1.Internet 协议(IP )
2.传输控制协议(TCP )和用户数据报文协议(UDP )
3.处于TCP 和UDP 之上的一组协议专门开发的应用程序。它们包括:TELNET ,文件传送协议(FTP ),域名服务(DNS )和简单的邮件传送程序(SMTP )等许多协议。
IP 功能:
IP 的主要目的是为数据输入/输出网络提供基本算法,为高层协议提供无连接的传送服务。这意味着在IP 将数据递交给接收站点以前不在传输站点和接收站点之间建立对话(虚拟链路)。它只是封装和传递数据,但不向发送者或接收者报告包的状态,不处理所遇到的故障。
TCP:
TCP (传输控制协议Transmission Control Protocol)是重要的传输层协议,传输层软件TCP 的目的是允许数据同网络上的另外站点进行可靠的交换。它能提供端口编号的译码,以识别主机的应用程序,而且完成数据的可靠传输。
,TCP 协议具有严格的内装差错检验算法确保数据的完整性。
TCP 是面向字节的顺序协议,这意味着包内的每个字节被分配一个顺序编号,并分配给每包一个顺序编号。
用户数据报文协议:
UDP (用户数据报协议User Datagram Protocol)也是TCP/IP 的传输层协议,它是无连接的,不可靠的传输服务。当接收数据时它不向发送方提供确认信息,它不提供输入包的顺序,如果出现丢失包或重份包的情况,也不会向发送方发出差错报文。
UDP 的主要作用是分配和管理端口编号,以正确无误的识别运行在网络站点上的个别应用程序。由于它执行功能时具有较低的开销,因而执行速度比TCP 快。它多半用于不需要可靠传输的应用程序,例如网络视频点播和视频会议等。 b. 网络编程基础
socket 概述:
linux中的网络编程通过socket 接口实现。Socket 既是一种特殊的IO ,它也是一种文件描述符。一个完整的Socket 都有一个相关描述{协议,本地地址,本地端口,远程地址,远程端口};每一个Socket 有一个本地的唯一Socket 号,由操作系统分配。
套接字有三种类型:
流式套接字(SOCK_STREAM):流式的套接字可以提供可靠的、面向连接的通讯流。它使用了TCP 协议。TCP 保证了数据传输的正确性和顺序性。
数据报套接字(SOCK_DGRAM):数据报套接字定义了一种无连接的服务,数据通过相互独立的报文进行传输,是无序的,并且不保证可靠,无差错。使用数据报协议UDP 协议。
原始套接字:原始套接字允许对低层协议如IP 或ICMP 直接访问,主要用于新的网络协议实现的测试等。
struct sockaddr {
unsigned short sa_family; /* address族, AF_xxx */
char sa_data[14];
}; /* 14 bytes的协议地址 */
,sa_family 一般来说, IPV4使用“AF_INET”。
sa_data 包含了一些远程电脑的地址、端口和套接字的数目,它里面的数据是杂溶在一起的。
struct sockaddr_in {
short int sin_family; /* Internet地址族 */
unsigned short int sin_port; /* 端口号 */
struct in_addr sin_addr; /* Internet地址 */
unsigned char sin_zero[8]; /* 添0(和struct sockaddr一样大小)*/ };
这两个数据类型是等效的,可以相互转换,通常使用sockaddr_in更为方便 地址字节序列转化:
因为每一个机器内部对变量的字节存储顺序不同(有的系统是高位在前,底位在后,而有的系统是底位在前,高位在后 ),而网络传输的数据大家是一定要统一顺序的。所以对与内部字节表示顺序和网络字节顺序不同的机器,就一定要对数据进行转换。
下面给出套接字字节转换程序的列表:
htons()——“Host to Network Short ” 主机字节顺序转换为网络字节顺序(对无符号短型进行操作2bytes )
htonl()——“Host to Network Long ” 主机字节顺序转换为网络字节顺序(对无符号长型进行操作4bytes )
ntohs()——“Network to Host Short ” 网络字节顺序转换为主机字节顺序(对无符号短型进行操作2bytes )
ntohl()——“Network to Host Long ” 网络字节顺序转换为主机字节顺序(对无符号长型进行操作4bytes )
,三. 程序设计原理图
四. 程序源代码
五.

Server.cpp
,#include
#include
#include
#include
#include
//创建套接字描述符
SOCKET server;
SOCKET client;
WSADATA WSAData;
int WSAreturn;
//用来存放ip 地址和端口号
struct sockaddr_in local;
struct sockaddr_in from;
//远程主机的地主长度
int fromlen = sizeof(from);
//信息缓冲区
char information[50];
//有客户登录时返回的第一条信息
char welcome[]="欢迎您登陆李仕贤主机!----零度工作室n"; //收到信息的缓冲区
char receive[256];
char chat[256];
char c;
int i=0;
bool cansend=false;
int GetIp()
{
//初始化 说明版本号
WSAreturn = WSAStartup(0x101,&WSAData);
if(WSAreturn)
{
printf("[server@root]#发生一个未知错误!n");
return 0;
}
//AF-INET代表Internet (TCP/IP)地址族
local.sin_family = AF_INET;
//ip为INADDR_ANY,系统会自动填入本机IP 地址
local.sin_addr.s_addr = INADDR_ANY;
//端口号 设为8888,以后通信就通过此端口
local.sin_port = htons((8888));
//创建套接字,指定是流式套接字是用tcp 协议
server = socket(AF_INET,SOCK_STREAM,0);
,if(server==INVALID_SOCKET )
{
printf("[server@root]#无法创建套接字!n");
return 0;
}
// 套接字绑定端口和ip 地址,所以信息到达主机后就能找到进程,,
if(bind(server,(sockaddr *)&local,sizeof(local))!=0)
{
printf("[server@root]#无法绑定套接字!n");
return 0;
}
//侦听 侦听数为5
if(listen(server,5)!=0)
{
printf("[server@root]#无法监听端口!n");
return 0;
}
while(true)
{
printf("[server@root]#正在等待用户连接...n");
//接受客户端的连接,没有连接时则阻塞。。。
client = accept(server,(struct sockaddr *)&from,&fromlen);
//有连接 ,则发送一条欢迎的信息
strcpy(information,inet_ntoa(from.sin_addr));
strcat(welcome,information);
printf("[server@root]#接受来自s的连接...n",inet_ntoa(from.sin_addr)); printf("[server@root]#正在发送欢迎消息...n");
//发送信息
send(client,welcome,strlen(welcome),0);
printf("[server@root]#欢迎消息信息已经成功发送至客户端!n");
while(1)
{
if(!cansend)
{
printf("[server@root]#正在等待对方发来消息...n");
cansend=false;
// 接受信息,,如果信息没有,则阻塞。。。
recv(client,receive,sizeof(receive),0);
printf("*********接受到的消息***********n");
printf("[server@root]#sn",receive);
printf("**************结束**************n");
,cansend=true;
}
else
{
printf("[server@root]#请输入下一条消息:"); scanf("s0",&chat);
send(client,chat,strlen(chat),0);
printf("n[server@root]#已经成功发送出信息!n"); cansend=false;
}
}
//关闭套接字
closesocket(client);
}
closesocket(server);
WSACleanup();
return 1;
}
void main()
{
int ok;
ok = GetIp(); // 套接字的创建,信息的发送和接收 if(ok==0)
printf("[server@root]#无法完成请求!n");
}
Client.cpp
#include
#include
#include
#include
#include
SOCKET client;
WSADATA WSAData;
int WSAreturn;
struct sockaddr_in to;
char information[256];
char welcome[]="我已经登陆到你的主机!n";
,//设置信息的缓冲区
char receive[256];
char chatto[256];
char servername[256];
char chatfrom[256];
char c;
long result;
bool cansend=true;
//连接主机。。。。
int connection()
{
WSAreturn = WSAStartup(0x101,&WSAData); //初始化。。。 if(WSAreturn)
{
printf("[server@root]#发生一个未知错误!n");
return 0;
}
//创建套接字,用来与服务器连接
client = socket(AF_INET,SOCK_STREAM,0);
//表示使用tcp 协议
to.sin_family = AF_INET;
//设置端口号,要转化为网络的大端的地址格式
to.sin_port = htons(8888);
while(true)
{
printf("[server@root]#请输入要登陆的IP:");
scanf("s",&servername);
//主机的ip 地址,要进行字节序列转化和地址格式转化
to.sin_addr.s_addr = inet_addr(servername);
printf("[server@root]#正在连接...n");
//连接主机,连接失败返回-1
result = connect(client,(struct sockaddr *)&to,sizeof(to)); if(SOCKET_ERROR==result)
{
// 连接失败
printf("[server@root]#无法连接到目标主机!n");
WSACleanup();
return 0;
}
else
{
,cansend=false;
//接收由服务器发来的信息
recv(client,receive,sizeof(receive),0); printf("*******欢迎消息消息*******n"); printf("[server@root]#sn",receive); printf("***********结束*********n"); cansend=true;
while(1)
{
if(cansend)
{
printf("[server@root]#请输入下一条信息:"); //从键盘获得信息
scanf("s0",&chatto);
// 将信息发送到服务器
send(client,chatto,strlen(chatto),0);
printf("n[server@root]#已经成功发送信息!n"); //cansend 置零 下一步接收信息
cansend=false;
}
else
{
printf("正在等待对方发来消息...n"); cansend=false;
//接收信息,信息还没到达时候就阻塞
recv(client,chatfrom,sizeof(chatfrom),0);
printf("*******接收到的消息*******n"); printf("[server@root]#sn",chatfrom); printf("***********结束*********n"); // 下一步发送信息
cansend=true;
}
}
}