日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux 多线程客户端服务端通信,[转载]多线程实现服务器和客户端、客户端和客户端通信;需要代码,留言...

發布時間:2024/7/23 linux 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux 多线程客户端服务端通信,[转载]多线程实现服务器和客户端、客户端和客户端通信;需要代码,留言... 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、實驗名稱

動手打造自己的?IM

二、實驗目的

1本次實驗旨在鍛煉大家的Socket編程能力,以日常生活中廣泛使用的IM軟件為背景,培養大家對于網絡編程的興趣。

2、通過本次實驗,培養linux環境下網絡編程能力,使得我們對網絡應用層的網絡應用軟件有了一個深入的理解,這對網絡課程的學習起到了很好的實踐作用。

三、實驗內容及步驟

實驗內容:本作業要求同學們完成一個簡陋的IM的客戶端和服務器端,實現一些最基本和最常用的IM功能:

客戶端功能:

1、4個以!開頭命令,!login登錄命令!list列出在線用戶命令!file傳輸文件命令!logoff注銷命令。

2、回顯功能:當其他用戶登錄或者登出時,客戶端會收到服務器的提示信息,當向另一個客戶端發送文件之后,也會收到該客戶端的提示信息。

3、聊天功能:兩個客戶端可以進行聊天:

以[username]:?開頭的行為其他用戶向你發送的聊天信息。

以>>[username]:?開頭的行為你向其他用戶發送的聊天信息。

服務器功能:

Server端基本架構:多進程并發服務器實現,為每個在線用戶分配一個進程用以和在線用戶保持通信,并在子進程退出(某用戶下線)時,回收子進程資源。

ü服務器端固定端口:8081

ü用戶登錄成功,反饋提示信息

ü維護在線用戶信息:包括IP地址和端口號,用戶名字,用戶密碼等

ü向在線用戶發出其他用戶上/下線提示信息

實驗步驟:

1、熟悉Linux下C語言的編程環境和編譯方法,學會用gedit來編寫并修改代碼及命令行工具。

2、學習有關socket方面的有關知識,嘗試著去編寫服務器端和客戶端的實現連接的代碼,最重要的是學會使用socket()、listen()、bind()、connect()、accept()等函數的使用方法,在此基礎上實現客戶端和服務器端的連接。

3、在實現客戶端和服務器端連接的基礎上編寫處理!login、!logoff、!list等簡單的命令(無需客戶端與客戶端交互),這個過程最重要的是學會send()、recv()函數的使用,傳遞套接字時要注意接收和發送的對應。

4、在實現了單個客戶端與服務器的用簡單命令交互的基礎上,學習線程的有關知識在服務器端創建多線程,實現服務器可以和多個客戶端交互的功能。此過程最重要的是學會線程創建和使用,最重要的是pthread_create(4個參數)的使用,其中關鍵的地方是線程函數的建立及其參數的傳遞,參數是socket,這樣才能在線程中實現與客戶端的交互。

5、在實現了多個客戶端與服務器進行交互的基礎上,就有可能實現客戶端與客戶端的交互,編程時一個很關鍵的地方就是所使用的數據結構,沒有一個存儲logined客戶端的數據結構,就很難實現客戶端與客戶端的交互。因此需要建立一個結構體來存儲客戶端的socket、port(可選)、username、flag(狀態)。

兩種方案:

1)從服務器獲得另一個客戶端的端口號和IP后,讓客戶端與客戶端建立連接,實現直接交互,這就是P2P結構,編程時我試著使用了這種方法,但是連接總是出問題。

2)通過服務器實現客戶端之間的交互,簡單來說就是客戶端把信息通過socket發送到服務器,服務器再把信息通過不同的socket發送到客戶端,這是建立在每個客戶端都有自己的socket的基礎上的。

我選擇了第二種方案來實現客戶端的交互。

6、編程進行到這里,我突然意識到了如果客戶端沒有監聽服務器的代碼,無法接收和識別服務器的信息是客戶端要發送的信息、還是服務其本身要發送的信息,思考良久,無奈之下只能大篇幅的修改代碼,在客戶端使用雙線程,一個用于監聽鍵盤的輸入,一個用于監聽服務器是否發送信息;這樣當鍵盤輸入時一個線程接收并負責向服務器發送信息,當收到服務器發送的信息時,另一個線程接收并把信息輸出到終端上。

7、在以上的基礎上,就可以實現客戶端的通話及文件的發送,最后就是調試程序并整理輸出的格式。

四、實驗分析

1,server.c編譯及運行結果:

圖1處于監聽狀態的服務器

2,開啟另外終端運行客戶端程序:

第一個用戶:Me,運行客戶端程序之后,使用命令!login登錄,成功登錄后會收到服務器的發送的信息,結果如下:

圖2?一個client登陸成功后的服務器

圖3第一個客戶端Me登陸成功

另起兩個終端第二個客戶端You和第三個客戶端Him登錄后結果如下:

圖4多個客戶端登陸后的服務器

3,指令!list的使用:

圖5?Me客戶端上執行!list命令

4,!logoff命令:當用戶Me執行!logoff后,客戶端顯示服務器發送的信息,此時使用!list指令,結果如下:

圖6客戶端Him執行!logoff命令

圖7客戶端Him執行!logoff命令后Me執行!list的結果

5,聊天功能演示:

圖8?Me客戶端和You客戶端進行通話

圖9You客戶端和Me客戶端通話

6,指令!file的使用,文件傳輸功能演示:

圖10You客戶端向Me發送lilufeng.pdf文件顯示成功

圖11?Me客戶端接收文件成功信息

7、幾種錯誤處理,結果如下:

圖12用戶名錯誤登錄失敗

圖13發送文件時用戶不在線、發送失敗

圖14Me想和You對話,You沒有登錄,連接失敗

五、實驗結論

難點:

1、本實驗是基于Linux環境下,使用C語言編寫而成,這兩者都需要實驗前進行深入的探索和學習,對我而言,加大了編程和實現的難度。

2、對socket和thread方面的知識可以說一無所知,編程的過程中要不斷地學習才能向前邁一小步。

感受:

1、這次實驗的過程中,我深知自己的知識的匱乏,實驗的過程可以說完全是一個探索的過程,對用到的函數我必須要在Dev等工具下先進性一定的應用和學習才能真正掌握其用法和內涵,實踐的過程中學到了很多的知識,而且在編程的后面階段感覺對這些知識已經能夠熟練地應用,最有說服力的就是那些函數的掌握,可見,軟件這個行業只有在實踐中才能真正的學到本領。

2、編程的前后,我的代碼被改了很多遍,因為開始編程的時候沒有一個整體的構思,只能走一步算一步,每走一步都是那么的艱難,線程的加入和數據結構的改變都使原來的代碼結構發生天翻地覆的變化,到最后在客戶端加入雙線程時整體的代碼又改了一遍,所以說這次試驗讓我感覺非常的累,而且過程中感覺網絡編程是那么的復雜,現在想想這些東西,還是很簡單的。由此,我明白了開發軟件前為什么要進行詳細的設計,看著是浪費時間,其實那是在節省時間和精力,而且是開發出一個軟件的基礎。

3、通過這次試驗讓我學會了關于網絡的socket和P2P等很多知識,這些知識在短期或者說今生難于忘記,當然還有操作系統方面的thread和process方面的知識。

4、同時我也感受到了IT人士的辛勞,其實我一直都在感受到,只不過這次更加強烈罷了,不過辛勞后,看到自己的成果和感到內心的充實,覺得付出還是值得的。

客戶端程序源碼:

//[浠g爜]

tcpclient.c

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define

SERVER_PORT 8081 ?//

define the defualt connect port

id

#define

BUFFER_SIZE 255 //buf size

int

clifd,length = 0;//socket size

char

buf[BUFFER_SIZE]; //the buffer of socket

pthread_t

thread;//thread discription

char

command[100],uName[20],pwd[20];

void

*listenServer(int);//listen and receive message from the server

int

cli_socket_connect_server(int);//create socket and connect the

server

int

main(int argc)

{

clifd =

cli_socket_connect_server(SERVER_PORT);//return the socket

while(1)

{ char

frontcmd[20],ch1,ch2;

int countcmd

=0,countFcmd=0;

memset(frontcmd,' ',sizeof(frontcmd));

memset(command,' ',sizeof(command));

memset(buf,' ',sizeof(buf));

while(ch1 =

getchar()) //input the command

{

if(ch1 == ' ')

{

while(ch2 =

getchar())

{

if(ch2 == 'n')

break;

else

command[countcmd++]

= ch2;

}

break;

}

else if(ch1 ==

'n')

break;

else

frontcmd[countFcmd++] = ch1;

}//input

over:frontcmd is the really command

if(frontcmd[0] ==

'>')//talk function process

{

strcpy(buf,">>");

send(clifd,buf,BUFFER_SIZE,0);

char *talkto;

talkto =

strtok(frontcmd,">:");

strcpy(buf,talkto);//talk to whom

strcat(buf,":");//:

is used to strtok in the server

strcat(buf,command);//what you send

send(clifd,buf,BUFFER_SIZE,0);

}

if(strcmp(frontcmd,"!logoff") == 0)//logoff command process

{

strcpy(buf,"!logoff");

send(clifd,buf,BUFFER_SIZE, 0);

strcpy(buf,uName);

send(clifd,buf,BUFFER_SIZE, 0 );

close(clifd);

pthread_exit(NULL);

break;

}//end of logoff

if

if(strcmp(frontcmd,"!list") == 0)//list command process

{

strcpy(buf,"!list");

send(clifd,buf,BUFFER_SIZE, 0 );

}//end of list

if

if(strcmp(frontcmd,"!login") == 0)//login command process

{

strcpy(buf,"!login");

send(clifd,buf,BUFFER_SIZE, 0 );

printf("User

name:t");

scanf("%s",uName);

printf("Password:t");

scanf("%s",pwd);

strcpy(buf,uName);

send(clifd,buf,BUFFER_SIZE, 0 );

length =

recv(clifd,buf,BUFFER_SIZE,0);

if

(length < 0)

{

printf(" error comes

when recieve data from server! send filen");

exit( 1 );

}

printf("From

server:nt%sn",buf);

if(pthread_create(&thread, NULL, (void

*)listenServer, (void *)clifd) == 0) //after login success create

the listenServer thread

{

printf("listen

thread create success!n");

}

else

{

printf("listen

thread create failed!n");

exit(1);

}

}//end of login

if

if(strcmp(frontcmd,"!file") == 0)

{

strcpy(buf,frontcmd);//send front command(!file) to the server

send(clifd,buf,BUFFER_SIZE,0);

char

*file,*toUser;

file =

strtok(command," =>");//file

toUser =

strtok(NULL," =>");//destination user

printf("filename:t%sntoUser:t%s",file,toUser);

strcpy(buf,toUser);//send the file to whom

send(clifd,buf,BUFFER_SIZE,0);

}//end of file

if

}//end of while

return 0;

}

void

*listenServer(int file_socket)

{

while(recv(file_socket,buf,BUFFER_SIZE,0)>0)

{

char *flagcmd =

NULL,*printInfo = NULL;

flagcmd =

strtok(buf,"|");

printInfo =

strtok(NULL,"|");

if(strcmp(flagcmd,"!list") == 0)//list the user that logined

now

printf("from

server:n%s",printInfo);

else

if(strcmp(flagcmd,"!logoff") == 0)//logoff

printf("from

server:nt%s",printInfo);

else

if(strcmp(flagcmd,"!file") == 0)//send the file

{

if(strcmp(printInfo,"0") == 0)//destination user does not login

printf("From

server:ntuser does not login,file failed!n");

else

//destination user logined

printf("nConnect

success!file success!n");

}

else

if(strcmp(flagcmd,"!msg") == 0)//receive the file message

{

printf("From

sever:nt%s",printInfo);

}

else

if(strcmp(flagcmd,"!talk") == 0)//talk message

{

if(strcmp(printInfo,"0") == 0)

printf("The user

does not login!n");

else

printf("%sn",printInfo);

}

else

printf("Please

debug!");

}

}

int

cli_socket_connect_server(int serverPort)

{

struct

sockaddr_in cliaddr;

socklen_t socklen

= ?sizeof(cliaddr);

char

sever[20];//store the IP

int

client_socket;

if((client_socket

= ?socket(AF_INET,SOCK_STREAM, 0

)) ?< ?0

)//create socket of the client

{

printf(" create

socket error!n ");

exit( 1 );

}

bzero(

& cliaddr,sizeof(cliaddr));

cliaddr.sin_family

= ?AF_INET;

inet_aton(sever,

& cliaddr.sin_addr);

cliaddr.sin_port

= ?htons(serverPort);//port of

the sever

cliaddr.sin_addr.s_addr ?=

htons(INADDR_ANY);//the same IP with the

sever.Connect auto!

if(connect(client_socket,(struct ?sockaddr * )

& cliaddr, socklen)

< ?0 )//connect

the server

{

printf(" can't

connect!n ");

exit( 1 );

}

return

client_socket; //return the socket

}

服務器端源碼:

//tcpserver.c

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define

SERVER_PORT 8081 ?//

define the defualt connect port

id

#define

LENGTH_OF_LISTEN_QUEUE 10 ?//

length of listen queue in server

#define

MAX_THREAD 10

#define

BUFFER_SIZE 255

#define

SUCCESS_MESSAGE "Login

Success!"

#define

FAIL_MESSAGE "Login Failed!"

#define

TOTAL_USER_NUM 6

struct

clientInformation

{

int flag;

//record

the struct state: 0 is empty

char loginUsr[20];

//the users that have logined

int socket;

//store the logined uses'

socket

};

struct

clientInformation clientInfo[TOTAL_USER_NUM];//logined users'

array

int

servfd,sever_socket; ?//the socket

int len=0;

//record the length of the socket

int numOfThread = 0;

//record the number of

threads

char users[6][10] =

{"Me","You","Him","Her","user","tmd"};//users that can login

char

buf[BUFFER_SIZE]; ?//the capacity of the

socket

pthread_t

thread[MAX_THREAD]; //thread discription

struct

sockaddr_in servaddr,cliaddr;

void*

docommand(int);//thread function

int main(int

argc)

{

int num;

for(num = 0; num

< TOTAL_USER_NUM; num++)

{

clientInfo[num].flag

= 0;

clientInfo[num].socket = 0;

}

if ?((servfd ?=

socket(AF_INET,SOCK_STREAM, 0 ))

< ?0 )//create

socket in the server

{

printf(" create socket

error!n ");

exit( 1

);

}

bzero( &

servaddr,sizeof(servaddr));

servaddr.sin_family ?=

AF_INET;

servaddr.sin_port ?=

htons(SERVER_PORT);

servaddr.sin_addr.s_addr ?=

htons(INADDR_ANY);

if(bind(servfd,(struct ?sockaddr

* ) & servaddr,sizeof(servaddr)) < 0

)//bind

{

printf(" bind to

port %d failure!n ",SERVER_PORT);

exit( 1

);

}

if(listen(servfd,LENGTH_OF_LISTEN_QUEUE)

< ?0

)//listen

{

printf("

call listen failure!n ");

exit( 1

);

}

while(numOfThread

< MAX_THREAD)

{

socklen_t length

= ?sizeof(cliaddr);

sever_socket ?=

accept(servfd,(struct ?sockaddr

* ) & cliaddr, & length);//accept

the login

if

(sever_socket ?<

0 )

{

printf("

error comes when call accept!n ");

break;

}

else

{

//void* arg[] =

{&sever_socket};

if(pthread_create(&thread[numOfThread++], NULL,

(void *)docommand, (void *)sever_socket) != 0)

printf("綰跨▼%d鍒涘緩澶辮觸!n",numOfThread); //create

the new thread to the login client

else

printf("綰跨▼%d琚垱寤簄",numOfThread);

}

}

close(servfd);

return ?0

;

}

void *docommand(int

sever_socket)

{

while

( 1 )

{// server loop will nerver exit unless any body kill the process

memset(buf,' ',sizeof(buf));

len

= ?recv(sever_socket, buf,

BUFFER_SIZE, 0); ?//recv the

command

if

(len < 0)

{

printf(" error comes when

recieve data from client ! " );

exit( 1 );

}

else

{

if(strcmp(buf,">>") == 0) //talk

process

{

len

= ?recv(sever_socket, buf,

BUFFER_SIZE, 0);//recv the user name that the file will be sent

to

if

(len < 0)

{

printf("error comes when

recieve data from client ! " );

exit( 1 );

}

char

temp[100],*talkto;

strcpy(temp,buf);//temp store what will be sent

talkto =

strtok(buf,":");

int j;

for(j = 0;j

< TOTAL_USER_NUM;j++)

{

if(clientInfo[j].flag == 1)

{

if(strcmp(clientInfo[j].loginUsr,talkto) == 0)

{

strcpy(buf,"!talk|");

strcat(buf,temp);//move temp(the information) to buf

send(clientInfo[j].socket,buf,BUFFER_SIZE,0);//send the talking

message to whom what you talk

break;

}

}

}

if(j ==

TOTAL_USER_NUM)

{

strcpy(buf,"!talk");

strcat(buf,"|0");//"0" == user does not login

send(sever_socket,buf,BUFFER_SIZE, 0 ); //send message(user does

not login)

}

}

else

if(strcmp(buf,"!file") == 0) ?//file process

{

len

= ?recv(sever_socket, buf,

BUFFER_SIZE, 0);//recv the user name that the file will be sent

to

if

(len < 0)

{

printf("error comes when

recieve data from client ! " );

exit( 1 );

}

int i;

for(i = 0;i

< TOTAL_USER_NUM;i++)

{

if(clientInfo[i].flag == 1)

{

if(strcmp(clientInfo[i].loginUsr,buf) == 0)

{

strcpy(buf,"!file|");

strcat(buf,"1");//"1" == user logined

send(sever_socket,buf,BUFFER_SIZE, 0 ); //send to the client who

send file(receiver)

strcpy(buf,"!msg|nreceived the file!n");

send(clientInfo[i].socket,buf,BUFFER_SIZE,0);//tell the client to

recv the file

break;

}

}

}

if(i ==

TOTAL_USER_NUM)

{

strcpy(buf,"!file");

strcat(buf,"|0");//"0" == user does not login

send(sever_socket,buf,BUFFER_SIZE, 0 ); //send message(user does

not login)

}

}//end of if

else

if(strcmp(buf,"!list") == 0) ?//list the logined users process

{

strcat(buf,"|");

int k;

for(k = 0; k

< TOTAL_USER_NUM; k++)

{

if(clientInfo[k].flag == 1)

{

strcat(buf,clientInfo[k].loginUsr);

strcat(buf,"n");

}

}

send(sever_socket,buf,BUFFER_SIZE,0); //send all logined users to

client

}//end of else if

1

else

if(strcmp(buf,"!logoff") == 0) ?// logoff process

{

while(1)

{

strcat(buf,"|logoff

success!n");

send(sever_socket,buf,BUFFER_SIZE,0); //send logoff success

message

memset(buf,' ',sizeof(buf));

len

= ?recv(sever_socket, buf,

BUFFER_SIZE, 0); ?//recv the login users name

int k;

for(k = 0; k

< TOTAL_USER_NUM; k++)//move it out from the

clientinformation struct

{

if(strcmp(buf,clientInfo[k].loginUsr) == 0)

{

strcpy(clientInfo[k].loginUsr," ");

clientInfo[k].flag =

0;

clientInfo[k].socket

= 0;

break;

}

}

close(sever_socket);

numOfThread--;

pthread_exit(NULL);

break;

}

}//end of else if

2

else

if(strcmp(buf,"!login") == 0)//login process

{

len

= ?recv(sever_socket, buf,

BUFFER_SIZE, 0); //recv the login user's name

if

(len < 0)

{

printf("error comes when

recieve data from client ! login" );

exit( 1 );

}

printf("from

client:%stIP:%stPort:%dn ",buf,

inet_ntoa(cliaddr.sin_addr),ntohs(cliaddr.sin_port));

int i;

for(i = 0;i

< TOTAL_USER_NUM;i++)//judge whether have this

user

{

if(strcmp(buf,users[i]) == 0)

{

for(i = 0;i

< TOTAL_USER_NUM;i++)

{

if(clientInfo[i].flag == 0)

{

strcpy(clientInfo[i].loginUsr,buf);

clientInfo[i].socket

= sever_socket;

clientInfo[i].flag =

1;

break;

}

}

strcpy(buf,SUCCESS_MESSAGE);

send(sever_socket,buf,BUFFER_SIZE, 0 ); //send login success

message

break;

}

}

if(i ==

TOTAL_USER_NUM)

{

printf("No user

called %s! Login failed!n",buf);

memset(buf,' ',sizeof(buf));

strcpy(buf,FAIL_MESSAGE);

send(sever_socket,buf,BUFFER_SIZE, 0 ); //send login failed

message

}

}//end of else if

3

} //end of else

}// end of while

}

又不懂得地方,歡迎留言詢問,我必盡力解答!

總結

以上是生活随笔為你收集整理的linux 多线程客户端服务端通信,[转载]多线程实现服务器和客户端、客户端和客户端通信;需要代码,留言...的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。