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

Server.cpp
,#include
#include
#include
#include
#include
//創(chuàng)建套接字描述符
SOCKET server;
SOCKET client;
WSADATA WSAData;
int WSAreturn;
//用來存放ip 地址和端口號
struct sockaddr_in local;
struct sockaddr_in from;
//遠程主機的地主長度
int fromlen = sizeof(from);
//信息緩沖區(qū)
char information[50];
//有客戶登錄時返回的第一條信息
char welcome[]="歡迎您登陸李仕賢主機!----零度工作室n"; //收到信息的緩沖區(qū)
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]#發(fā)生一個未知錯誤!n");
return 0;
}
//AF-INET代表Internet (TCP/IP)地址族
local.sin_family = AF_INET;
//ip為INADDR_ANY,系統(tǒng)會自動填入本機IP 地址
local.sin_addr.s_addr = INADDR_ANY;
//端口號 設為8888,以后通信就通過此端口
local.sin_port = htons((8888));
//創(chuàng)建套接字,指定是流式套接字是用tcp 協(xié)議
server = socket(AF_INET,SOCK_STREAM,0);
,if(server==INVALID_SOCKET )
{
printf("[server@root]#無法創(chuàng)建套接字!n");
return 0;
}
// 套接字綁定端口和ip 地址,所以信息到達主機后就能找到進程,,
if(bind(server,(sockaddr *)&local,sizeof(local))!=0)
{
printf("[server@root]#無法綁定套接字!n");
return 0;
}
//偵聽 偵聽數(shù)為5
if(listen(server,5)!=0)
{
printf("[server@root]#無法監(jiān)聽端口!n");
return 0;
}
while(true)
{
printf("[server@root]#正在等待用戶連接...n");
//接受客戶端的連接,沒有連接時則阻塞。。。
client = accept(server,(struct sockaddr *)&from,&fromlen);
//有連接 ,則發(fā)送一條歡迎的信息
strcpy(information,inet_ntoa(from.sin_addr));
strcat(welcome,information);
printf("[server@root]#接受來自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]#正在等待對方發(fā)來消息...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]#已經(jīng)成功發(fā)送出信息!n"); cansend=false;
}
}
//關閉套接字
closesocket(client);
}
closesocket(server);
WSACleanup();
return 1;
}
void main()
{
int ok;
ok = GetIp(); // 套接字的創(chuàng)建,信息的發(fā)送和接收 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[]="我已經(jīng)登陸到你的主機!n";
,//設置信息的緩沖區(qū)
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]#發(fā)生一個未知錯誤!n");
return 0;
}
//創(chuàng)建套接字,用來與服務器連接
client = socket(AF_INET,SOCK_STREAM,0);
//表示使用tcp 協(xié)議
to.sin_family = AF_INET;
//設置端口號,要轉化為網(wǎng)絡的大端的地址格式
to.sin_port = htons(8888);
while(true)
{
printf("[server@root]#請輸入要登陸的IP:");
scanf("s",&servername);
//主機的ip 地址,要進行字節(jié)序列轉化和地址格式轉化
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;
//接收由服務器發(fā)來的信息
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);
// 將信息發(fā)送到服務器
send(client,chatto,strlen(chatto),0);
printf("n[server@root]#已經(jīng)成功發(fā)送信息!n"); //cansend 置零 下一步接收信息
cansend=false;
}
else
{
printf("正在等待對方發(fā)來消息...n"); cansend=false;
//接收信息,信息還沒到達時候就阻塞
recv(client,chatfrom,sizeof(chatfrom),0);
printf("*******接收到的消息*******n"); printf("[server@root]#sn",chatfrom); printf("***********結束*********n"); // 下一步發(fā)送信息
cansend=true;
}
}
}