計算機網(wǎng)絡實驗
簡單UDP套接字編程
這是學校老師自己改進了一點的題目。我預習了好久才搞明白风秤,同學來問的時候碉咆,一大堆簡單問題實在是不想回答...所以,這時候我覺得博客是個好東西漫玄!
我的任務是做客戶端和服務器,并通過修改服務器压彭,實現(xiàn)在客戶端輸入GetTime睦优,然后經(jīng)過服務器返回當前系統(tǒng)時間**
==首先,Ubuntu系統(tǒng)==
這個是不可少的壮不,因為我們學的這個套接字就是在ubuntu上實現(xiàn)的汗盘,我是裝的ubuntu16.04,沒條件的裝虛擬機也可以询一。
此次UDP套接字程序步驟
- 創(chuàng)建套接字
- 命名套接字
- 在服務器上隐孽,等待消息
- 在客戶端上,發(fā)送消息
- 將響應發(fā)送回客戶端
- 關閉套接字
具體程序不給出健蕊,網(wǎng)上參考有很多菱阵,為了節(jié)省時間,老師給的代碼绊诲,雖然有自己修改的送粱,但是不敢發(fā)出來,畢竟老師還是很牛批的掂之,萬一找到我追究責任抗俄,那我不扯犢子了嘛脆丁。所以主要寫寫例如sendto,recvfrom之類的用法。
1.創(chuàng)建套接字
使用系統(tǒng)命令==socket==來創(chuàng)建套接字
int socket(int domain, int type, int protocol);
里面三個參數(shù)具體類型我還沒搞懂动雹,就不發(fā)了emmm
2.命名套接字
創(chuàng)建的套接字不能直接使用槽卫,要對其進行命名,使用系統(tǒng)的==bind==進行命名胰蝠,給該套接字關聯(lián)一個IP和端口號
int bind(int socket, const struct sockaddr *address, size_t address_len);
socket:服務器或者客戶端自己創(chuàng)建的socket
address:服務器或者客戶端自己的地址信息(協(xié)議族歼培、IP、端口號)
address_len:服務器或者客戶端自己的地址信息的長度
3. 在服務器上茸塞,等待消息
在服務器通過==recvfrom==接收來自客戶端的消息躲庄,請記住我們接下來要修改服務器代碼實現(xiàn)返回==時間==的就是在這一步后面修改代碼。
服務器在循環(huán)里面不斷調(diào)用==recvfrom==函數(shù)钾虐,接收客戶的數(shù)據(jù)噪窘,并輸出接收到的客戶數(shù)據(jù)的長度和具體內(nèi)容。
int recvfrom(int socket, void *buffer, size_t length, int flags, struct sockaddr *src_addr, socklen_t *src_len);
socket:標識一個已連接套接口的描述字效扫。
buffer:接收數(shù)據(jù)緩沖區(qū)倔监。
length:緩沖區(qū)長度。
flags:調(diào)用操作方式菌仁。
src_addr:(可選)指針浩习,指向裝有源地址的緩沖區(qū)。
src_len:(可選)指針济丘,指向from緩沖區(qū)長度值谱秽。
以上是普通的套接字編程,在此次實驗中還要求了修改服務器代碼來實現(xiàn)返回客戶端的是==系統(tǒng)時間==闪盔。所以這里我們主要注意一下==buffer==弯院;
4.在客戶端上辱士,發(fā)送消息
UDP是無連接的泪掀,所以客戶端可以直接向服務器發(fā)送消息,通過==sendto==向服務器發(fā)送
int sendto(int socket, const void *buffer, size_t length, int flags, const struct sockaddr *dest_addr, socklen_t dest_len);
socket:一個標識套接口的描述字颂碘。
buffer:包含待發(fā)送數(shù)據(jù)的緩沖區(qū)异赫。
length:buf緩沖區(qū)中數(shù)據(jù)的長度。
flags:調(diào)用方式標志位头岔。
dest_addr:(可選)指針塔拳,指向目的套接口的地址。
dest_len:to所指地址的長度峡竣。
5.將響應發(fā)送回客戶端
依舊通過==sendto==將響應發(fā)回客戶端由客戶端==recvform==后輸出
6.關閉套接字
可以使用系統(tǒng)的==close==關閉套接字
close();
以上那些內(nèi)容網(wǎng)上都可以搜到靠抑,也許比我還詳細。所以我們這個主要要的在修改服務器代碼适掰,將給客戶端發(fā)送的數(shù)據(jù)更改為系統(tǒng)時間
題目是在客戶端輸入GetTime然后顯示系統(tǒng)時間颂碧。輸入其他字符串荠列,返回原字符串
還是之前讓注意的==recvfrom==里面的==buffer==,這是我們要判斷的载城,在服務器接收的內(nèi)容存在==buffer==中肌似,而==recvform==返回的值我們設為==n==,這是==buffer==的長度诉瓦,也就是你輸入的字符存在于==buffer==中.
我們可以建立一個time_p[]來存你要對比的字符串川队,也就是GetTime,但是要注意的是你在客戶端輸入的數(shù)據(jù)基本上是帶有回車的睬澡,這樣單純的對比是會出錯的固额,因為自己設置的對比用數(shù)組不含有回車.
所以我們要在預設的數(shù)組中添加回車。這個過程中要時刻注意自己的數(shù)組和讀取的客戶端發(fā)來的數(shù)組的結束標志和換行煞聪。
只需要在用==strcmp==判斷出接收的數(shù)據(jù)和自己預存的數(shù)據(jù)是否一樣对雪,是則將緩存區(qū)數(shù)據(jù)更改為系統(tǒng)時間(這一步要記住通過==strlen==判斷字符串長度并修改==n==,因為我們發(fā)送給客戶端時要用緩沖區(qū)長度米绕,如果不修改瑟捣,會導致發(fā)送的數(shù)據(jù)缺失),否則直接返回栅干。
補充時間函數(shù)
#include<stdio.h>
#include<time.h>
int main()
{
time_t timep;
time (&timep);
printf("%s",ctime(&timep));
return 0;
}
這是我自己修改服務器時更改的部分代碼迈套,有變動。而且碱鳞,值得注意的是因為是在死循環(huán)里不斷接收客戶端發(fā)來的數(shù)據(jù)桑李,我出現(xiàn)了數(shù)據(jù)有些重復了上次輸入的。所以最好還是在死循環(huán)內(nèi)用==memset==清空一下==buffer==窿给。我清空后就避開了這個錯誤贵白。
char time_p[] = "GetTime\n";
time_t timep;
time (&timep);
if(strcmp(buffer,time_p) == 0)
{
memset(buffer,0,sizeof(mesg));
strcpy(buffer,ctime(&timep));
k = strlen(buffer);
buffer[k] = '\r';
buffer[k+1] = '\0';
n = k+1;
}
說實話,這個預習還真是惡心崩泡。禁荒。。因為沒接觸過角撞,“弄清”這些函數(shù)花了好久呛伴。還一大堆東西沒弄明白。
倉促寫個這玩意谒所。難免有錯誤热康,發(fā)現(xiàn)請指出。劣领。姐军。