ai-zjhcc計(jì)算機(jī)網(wǎng)路課程設(shè)計(jì)
、.~① 我們‖打〈敗〉了敵人。②我們‖〔把敵人〕打〈敗〉了。中南林業(yè)科技大學(xué) 計(jì)算機(jī)與信息工程學(xué)院計(jì)算機(jī)網(wǎng)絡(luò)課程設(shè)計(jì)報(bào)告局域網(wǎng)聊天 ,班級(jí):08通信2班 學(xué)號(hào):20082
、
.~
① 我們‖打〈敗〉了敵人。
②我們‖〔把敵人〕打〈敗〉了。
中南林業(yè)科技大學(xué) 計(jì)算機(jī)與信息工程學(xué)院
計(jì)算機(jī)網(wǎng)絡(luò)課程設(shè)計(jì)報(bào)告
局
域
網(wǎng)
聊
天
,班級(jí):08通信2班 學(xué)號(hào):20082226
一. 設(shè)計(jì)的目的和意義
1. 在學(xué)習(xí)理論的同時(shí),加強(qiáng)動(dòng)手能力
2. 學(xué)習(xí)并掌握網(wǎng)絡(luò)編程
3. 實(shí)際應(yīng)用計(jì)算機(jī)網(wǎng)絡(luò)知識(shí)
意義:對(duì)以后的畢業(yè)設(shè)計(jì)打下基礎(chǔ),鍛煉個(gè)人的學(xué)習(xí)和查閱資料的能力以及對(duì)課外相關(guān)本專業(yè)知識(shí)的了解。
二. 設(shè)計(jì)的理論基礎(chǔ)
a.TCP/IP協(xié)議概述
TCP/IP 實(shí)際上一個(gè)一起工作的通信家族,為網(wǎng)際數(shù)據(jù)通信提供通路。為討論方便可將
TCP/IP 協(xié)議組大體上分為三部分:
1.Internet 協(xié)議(IP )
2.傳輸控制協(xié)議(TCP )和用戶數(shù)據(jù)報(bào)文協(xié)議(UDP )
3.處于TCP 和UDP 之上的一組協(xié)議專門開(kāi)發(fā)的應(yīng)用程序。它們包括:TELNET ,文件傳送協(xié)議(FTP ),域名服務(wù)(DNS )和簡(jiǎn)單的郵件傳送程序(SMTP )等許多協(xié)議。
IP 功能:
IP 的主要目的是為數(shù)據(jù)輸入/輸出網(wǎng)絡(luò)提供基本算法,為高層協(xié)議提供無(wú)連接的傳送服務(wù)。這意味著在IP 將數(shù)據(jù)遞交給接收站點(diǎn)以前不在傳輸站點(diǎn)和接收站點(diǎn)之間建立對(duì)話(虛擬鏈路)。它只是封裝和傳遞數(shù)據(jù),但不向發(fā)送者或接收者報(bào)告包的狀態(tài),不處理所遇到的故障。
TCP:
TCP (傳輸控制協(xié)議Transmission Control Protocol)是重要的傳輸層協(xié)議,傳輸層軟件TCP 的目的是允許數(shù)據(jù)同網(wǎng)絡(luò)上的另外站點(diǎn)進(jìn)行可靠的交換。它能提供端口編號(hào)的譯碼,以識(shí)別主機(jī)的應(yīng)用程序,而且完成數(shù)據(jù)的可靠傳輸。
,TCP 協(xié)議具有嚴(yán)格的內(nèi)裝差錯(cuò)檢驗(yàn)算法確保數(shù)據(jù)的完整性。
TCP 是面向字節(jié)的順序協(xié)議,這意味著包內(nèi)的每個(gè)字節(jié)被分配一個(gè)順序編號(hào),并分配給每包一個(gè)順序編號(hào)。
用戶數(shù)據(jù)報(bào)文協(xié)議:
UDP (用戶數(shù)據(jù)報(bào)協(xié)議User Datagram Protocol)也是TCP/IP 的傳輸層協(xié)議,它是無(wú)連接的,不可靠的傳輸服務(wù)。當(dāng)接收數(shù)據(jù)時(shí)它不向發(fā)送方提供確認(rèn)信息,它不提供輸入包的順序,如果出現(xiàn)丟失包或重份包的情況,也不會(huì)向發(fā)送方發(fā)出差錯(cuò)報(bào)文。
UDP 的主要作用是分配和管理端口編號(hào),以正確無(wú)誤的識(shí)別運(yùn)行在網(wǎng)絡(luò)站點(diǎn)上的個(gè)別應(yīng)用程序。由于它執(zhí)行功能時(shí)具有較低的開(kāi)銷,因而執(zhí)行速度比TCP 快。它多半用于不需要可靠傳輸?shù)膽?yīng)用程序,例如網(wǎng)絡(luò)視頻點(diǎn)播和視頻會(huì)議等。 b. 網(wǎng)絡(luò)編程基礎(chǔ)
socket 概述:
linux中的網(wǎng)絡(luò)編程通過(guò)socket 接口實(shí)現(xiàn)。Socket 既是一種特殊的IO ,它也是一種文件描述符。一個(gè)完整的Socket 都有一個(gè)相關(guān)描述{協(xié)議,本地地址,本地端口,遠(yuǎn)程地址,遠(yuǎn)程端口};每一個(gè)Socket 有一個(gè)本地的唯一Socket 號(hào),由操作系統(tǒng)分配。
套接字有三種類型:
流式套接字(SOCK_STREAM):流式的套接字可以提供可靠的、面向連接的通訊流。它使用了TCP 協(xié)議。TCP 保證了數(shù)據(jù)傳輸?shù)恼_性和順序性。
數(shù)據(jù)報(bào)套接字(SOCK_DGRAM):數(shù)據(jù)報(bào)套接字定義了一種無(wú)連接的服務(wù),數(shù)據(jù)通過(guò)相互獨(dú)立的報(bào)文進(jìn)行傳輸,是無(wú)序的,并且不保證可靠,無(wú)差錯(cuò)。使用數(shù)據(jù)報(bào)協(xié)議UDP 協(xié)議。
原始套接字:原始套接字允許對(duì)低層協(xié)議如IP 或ICMP 直接訪問(wèn),主要用于新的網(wǎng)絡(luò)協(xié)議實(shí)現(xiàn)的測(cè)試等。
struct sockaddr {
unsigned short sa_family; /* address族, AF_xxx */
char sa_data[14];
}; /* 14 bytes的協(xié)議地址 */
,sa_family 一般來(lái)說(shuō), IPV4使用“AF_INET”。
sa_data 包含了一些遠(yuǎn)程電腦的地址、端口和套接字的數(shù)目,它里面的數(shù)據(jù)是雜溶在一起的。
struct sockaddr_in {
short int sin_family; /* Internet地址族 */
unsigned short int sin_port; /* 端口號(hào) */
struct in_addr sin_addr; /* Internet地址 */
unsigned char sin_zero[8]; /* 添0(和struct sockaddr一樣大小)*/ };
這兩個(gè)數(shù)據(jù)類型是等效的,可以相互轉(zhuǎn)換,通常使用sockaddr_in更為方便 地址字節(jié)序列轉(zhuǎn)化:
因?yàn)槊恳粋€(gè)機(jī)器內(nèi)部對(duì)變量的字節(jié)存儲(chǔ)順序不同(有的系統(tǒng)是高位在前,底位在后,而有的系統(tǒng)是底位在前,高位在后 ),而網(wǎng)絡(luò)傳輸?shù)臄?shù)據(jù)大家是一定要統(tǒng)一順序的。所以對(duì)與內(nèi)部字節(jié)表示順序和網(wǎng)絡(luò)字節(jié)順序不同的機(jī)器,就一定要對(duì)數(shù)據(jù)進(jìn)行轉(zhuǎn)換。
下面給出套接字字節(jié)轉(zhuǎn)換程序的列表:
htons()——“Host to Network Short ” 主機(jī)字節(jié)順序轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)順序(對(duì)無(wú)符號(hào)短型進(jìn)行操作2bytes )
htonl()——“Host to Network Long ” 主機(jī)字節(jié)順序轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)順序(對(duì)無(wú)符號(hào)長(zhǎng)型進(jìn)行操作4bytes )
ntohs()——“Network to Host Short ” 網(wǎng)絡(luò)字節(jié)順序轉(zhuǎn)換為主機(jī)字節(jié)順序(對(duì)無(wú)符號(hào)短型進(jìn)行操作2bytes )
ntohl()——“Network to Host Long ” 網(wǎng)絡(luò)字節(jié)順序轉(zhuǎn)換為主機(jī)字節(jié)順序(對(duì)無(wú)符號(hào)長(zhǎng)型進(jìn)行操作4bytes )
,三. 程序設(shè)計(jì)原理圖
四. 程序源代碼
五.

Server.cpp
,#include
#include
#include
#include
#include
//創(chuàng)建套接字描述符
SOCKET server;
SOCKET client;
WSADATA WSAData;
int WSAreturn;
//用來(lái)存放ip 地址和端口號(hào)
struct sockaddr_in local;
struct sockaddr_in from;
//遠(yuǎn)程主機(jī)的地主長(zhǎng)度
int fromlen = sizeof(from);
//信息緩沖區(qū)
char information[50];
//有客戶登錄時(shí)返回的第一條信息
char welcome[]="歡迎您登陸李仕賢主機(jī)!----零度工作室n"; //收到信息的緩沖區(qū)
char receive[256];
char chat[256];
char c;
int i=0;
bool cansend=false;
int GetIp()
{
//初始化 說(shuō)明版本號(hào)
WSAreturn = WSAStartup(0x101,&WSAData);
if(WSAreturn)
{
printf("[server@root]#發(fā)生一個(gè)未知錯(cuò)誤!n");
return 0;
}
//AF-INET代表Internet (TCP/IP)地址族
local.sin_family = AF_INET;
//ip為INADDR_ANY,系統(tǒng)會(huì)自動(dòng)填入本機(jī)IP 地址
local.sin_addr.s_addr = INADDR_ANY;
//端口號(hào) 設(shè)為8888,以后通信就通過(guò)此端口
local.sin_port = htons((8888));
//創(chuàng)建套接字,指定是流式套接字是用tcp 協(xié)議
server = socket(AF_INET,SOCK_STREAM,0);
,if(server==INVALID_SOCKET )
{
printf("[server@root]#無(wú)法創(chuàng)建套接字!n");
return 0;
}
// 套接字綁定端口和ip 地址,所以信息到達(dá)主機(jī)后就能找到進(jìn)程,,
if(bind(server,(sockaddr *)&local,sizeof(local))!=0)
{
printf("[server@root]#無(wú)法綁定套接字!n");
return 0;
}
//偵聽(tīng) 偵聽(tīng)數(shù)為5
if(listen(server,5)!=0)
{
printf("[server@root]#無(wú)法監(jiān)聽(tīng)端口!n");
return 0;
}
while(true)
{
printf("[server@root]#正在等待用戶連接...n");
//接受客戶端的連接,沒(méi)有連接時(shí)則阻塞。。。
client = accept(server,(struct sockaddr *)&from,&fromlen);
//有連接 ,則發(fā)送一條歡迎的信息
strcpy(information,inet_ntoa(from.sin_addr));
strcat(welcome,information);
printf("[server@root]#接受來(lái)自s的連接...n",inet_ntoa(from.sin_addr)); printf("[server@root]#正在發(fā)送歡迎消息...n");
//發(fā)送信息
send(client,welcome,strlen(welcome),0);
printf("[server@root]#歡迎消息信息已經(jīng)成功發(fā)送至客戶端!n");
while(1)
{
if(!cansend)
{
printf("[server@root]#正在等待對(duì)方發(fā)來(lái)消息...n");
cansend=false;
// 接受信息,,如果信息沒(méi)有,則阻塞。。。
recv(client,receive,sizeof(receive),0);
printf("*********接受到的消息***********n");
printf("[server@root]#sn",receive);
printf("**************結(jié)束**************n");
,cansend=true;
}
else
{
printf("[server@root]#請(qǐng)輸入下一條消息:"); scanf("s0",&chat);
send(client,chat,strlen(chat),0);
printf("n[server@root]#已經(jīng)成功發(fā)送出信息!n"); cansend=false;
}
}
//關(guān)閉套接字
closesocket(client);
}
closesocket(server);
WSACleanup();
return 1;
}
void main()
{
int ok;
ok = GetIp(); // 套接字的創(chuàng)建,信息的發(fā)送和接收 if(ok==0)
printf("[server@root]#無(wú)法完成請(qǐng)求!n");
}
Client.cpp
#include
#include
#include
#include
#include
SOCKET client;
WSADATA WSAData;
int WSAreturn;
struct sockaddr_in to;
char information[256];
char welcome[]="我已經(jīng)登陸到你的主機(jī)!n";
,//設(shè)置信息的緩沖區(qū)
char receive[256];
char chatto[256];
char servername[256];
char chatfrom[256];
char c;
long result;
bool cansend=true;
//連接主機(jī)。。。。
int connection()
{
WSAreturn = WSAStartup(0x101,&WSAData); //初始化。。。 if(WSAreturn)
{
printf("[server@root]#發(fā)生一個(gè)未知錯(cuò)誤!n");
return 0;
}
//創(chuàng)建套接字,用來(lái)與服務(wù)器連接
client = socket(AF_INET,SOCK_STREAM,0);
//表示使用tcp 協(xié)議
to.sin_family = AF_INET;
//設(shè)置端口號(hào),要轉(zhuǎn)化為網(wǎng)絡(luò)的大端的地址格式
to.sin_port = htons(8888);
while(true)
{
printf("[server@root]#請(qǐng)輸入要登陸的IP:");
scanf("s",&servername);
//主機(jī)的ip 地址,要進(jìn)行字節(jié)序列轉(zhuǎn)化和地址格式轉(zhuǎn)化
to.sin_addr.s_addr = inet_addr(servername);
printf("[server@root]#正在連接...n");
//連接主機(jī),連接失敗返回-1
result = connect(client,(struct sockaddr *)&to,sizeof(to)); if(SOCKET_ERROR==result)
{
// 連接失敗
printf("[server@root]#無(wú)法連接到目標(biāo)主機(jī)!n");
WSACleanup();
return 0;
}
else
{
,cansend=false;
//接收由服務(wù)器發(fā)來(lái)的信息
recv(client,receive,sizeof(receive),0); printf("*******歡迎消息消息*******n"); printf("[server@root]#sn",receive); printf("***********結(jié)束*********n"); cansend=true;
while(1)
{
if(cansend)
{
printf("[server@root]#請(qǐng)輸入下一條信息:"); //從鍵盤獲得信息
scanf("s0",&chatto);
// 將信息發(fā)送到服務(wù)器
send(client,chatto,strlen(chatto),0);
printf("n[server@root]#已經(jīng)成功發(fā)送信息!n"); //cansend 置零 下一步接收信息
cansend=false;
}
else
{
printf("正在等待對(duì)方發(fā)來(lái)消息...n"); cansend=false;
//接收信息,信息還沒(méi)到達(dá)時(shí)候就阻塞
recv(client,chatfrom,sizeof(chatfrom),0);
printf("*******接收到的消息*******n"); printf("[server@root]#sn",chatfrom); printf("***********結(jié)束*********n"); // 下一步發(fā)送信息
cansend=true;
}
}
}