【移動(dòng)應(yīng)用開發(fā)技術(shù)】C++ SOCKET多線程怎么實(shí)現(xiàn)聊天小程序_第1頁
【移動(dòng)應(yīng)用開發(fā)技術(shù)】C++ SOCKET多線程怎么實(shí)現(xiàn)聊天小程序_第2頁
【移動(dòng)應(yīng)用開發(fā)技術(shù)】C++ SOCKET多線程怎么實(shí)現(xiàn)聊天小程序_第3頁
【移動(dòng)應(yīng)用開發(fā)技術(shù)】C++ SOCKET多線程怎么實(shí)現(xiàn)聊天小程序_第4頁
【移動(dòng)應(yīng)用開發(fā)技術(shù)】C++ SOCKET多線程怎么實(shí)現(xiàn)聊天小程序_第5頁
已閱讀5頁,還剩5頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

【移動(dòng)應(yīng)用開發(fā)技術(shù)】C++SOCKET多線程怎么實(shí)現(xiàn)聊天小程序

本篇內(nèi)容介紹了“C++SOCKET多線程怎么實(shí)現(xiàn)聊天小程序”的有關(guān)知識(shí),在實(shí)際案例的操作過程中,不少人都會(huì)遇到這樣的困境,接下來就讓在下帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!TCP/IP協(xié)議與SOCKET什么是網(wǎng)絡(luò)協(xié)議?計(jì)算機(jī)網(wǎng)絡(luò)中,各個(gè)實(shí)體之間的數(shù)據(jù)交換必須遵守事先約定好的規(guī)則,這些規(guī)則就稱為協(xié)議。網(wǎng)絡(luò)協(xié)議的組成要素有:1.語法,數(shù)據(jù)與控制信息的結(jié)構(gòu)或格式2.語義:需要發(fā)出何種控制信息,完成哪些動(dòng)作以及做出何種響應(yīng)3.時(shí)序:事件實(shí)現(xiàn)順序的詳細(xì)說明在一個(gè)網(wǎng)絡(luò)協(xié)議中,通信的實(shí)體的相同層次的結(jié)構(gòu)必須執(zhí)行相同的協(xié)議,這是協(xié)議的對等性原則。TCP/IP體系結(jié)構(gòu)與SOCKET關(guān)于TCP/IP體系結(jié)構(gòu)的詳細(xì)內(nèi)容本文不做論述,如果你沒有這方面的知識(shí)想要快速理解這個(gè)東西,可以把網(wǎng)絡(luò)通信類比成兩個(gè)人之間寫信。你的信件就是通信過程中要傳遞的消息或者數(shù)據(jù),而網(wǎng)絡(luò)協(xié)議對你的“信件”進(jìn)行了包裝,比如給你貼了郵票、包了信封、投進(jìn)了郵箱,然后你的“信件”就能通過郵局送到收信人那里。SOCKET(套接字)是TCP/IP網(wǎng)絡(luò)操作系統(tǒng)為網(wǎng)絡(luò)程序開發(fā)提供的典型網(wǎng)絡(luò)編程界面,進(jìn)程通過SOCKET發(fā)送消息和接收消息。你可以把SOCKET看作一道“門”,發(fā)送消息的進(jìn)程從“門”把消息推出去;消息被推出之后利用下層的通信設(shè)施傳遞到接收進(jìn)程所在的“門”;然后接收進(jìn)程再從“門”把消息拉進(jìn)去。套接字SOCKET又分為數(shù)據(jù)報(bào)套接字和流式套接字,分別使用UDP協(xié)議和TCP協(xié)議。SOCKET編程我們嘗試編寫一個(gè)單播聊天室,這個(gè)聊天室可以讓多個(gè)客戶端與服務(wù)器端進(jìn)行連接,而單播的意思是各個(gè)客戶端只能與服務(wù)端進(jìn)行單獨(dú)通信,不同客戶端之間無法通信。為了實(shí)現(xiàn)這個(gè)目標(biāo)我們還需要用到多線程。整體實(shí)現(xiàn)思路如下圖:話不多說,上代碼。Server端#include

"stdafx.h"

#include<WinSock2.h>

#include<string.h>

#include<iostream>

#pragma

comment

(lib,

"ws2_32.lib")

using

namespace

std;

const

int

PORT

=

8000;

#define

IP

"127.0.0.1"

#define

MaxClient

10//最多能接受同時(shí)在線的客戶端數(shù)量,可以隨意修改

#define

MaxBufSize

1024

int

num

=0;//客戶端數(shù)量計(jì)數(shù)器

#define

_CRT_SECURE_NO_WARINGS

//服務(wù)線程

DWORD

WINAPI

SeverThread(LPVOID

lpParameter)

{

//新建一個(gè)SOCKET用于通信

SOCKET

*ClientSocket

=

(SOCKET*)lpParameter;

int

receByt

=

0;

char

RecvBuf[MaxBufSize];

char

SendBuf[MaxBufSize];

char

exitBuf[5];

//開始接收

while

(1)

{

receByt

=

recv(*ClientSocket,

RecvBuf,

sizeof(RecvBuf),

0);

if

(receByt

>

0)

{

//當(dāng)客戶端發(fā)來的消息是“exit”,就關(guān)閉連接

if

(strlen(RecvBuf)==4)

{

for

(int

i

=

0;

i

<

5;

i++)

{

exitBuf[i]

=

RecvBuf[i];

}

int

flag

=

strcmp(exitBuf,

"exit");

if

(flag==0)//接收到exit消息

{

cout

<<

"client

"

<<

*ClientSocket

<<

"

exit!"

<<

endl;

num--;

send(*ClientSocket,

"Your

server

has

been

closed",

sizeof(SendBuf),

0);

closesocket(*ClientSocket);

return

0;

}

}

cout

<<

"receive

message

:"

<<

RecvBuf

<<

"

from

client:"

<<

*ClientSocket

<<

endl;

}

else

{

//下面說到的客戶端關(guān)閉連接是指客戶端掉線了

if

(WSAGetLastError()

==

10054)//檢測到客戶端關(guān)閉連接

{

cout

<<

"client

"

<<

*ClientSocket

<<

"

exit!"

<<

endl;

closesocket(*ClientSocket);

num--;

return

0;

}

else//接收失敗顯示錯(cuò)誤信息

{

cout

<<

"failed

to

receive,Error:"

<<

WSAGetLastError()

<<

endl;

break;

}

}

memset(RecvBuf,

0,

1024);

cout

<<

"input

your

message

to

client:"

<<

endl;

scanf_s("%s",SendBuf,MaxBufSize);

int

k

=

0;

k

=

send(*ClientSocket,

SendBuf,

sizeof(SendBuf),

0);

if

(k

<

0)

{

if

(WSAGetLastError()==10054)//檢測到客戶端主動(dòng)關(guān)閉連接

{

cout

<<

"client

"

<<

*ClientSocket

<<

"

exit!"

<<

endl;

closesocket(*ClientSocket);

num--;

return

0;

}

else//發(fā)送失敗顯示錯(cuò)誤信息

cout

<<

"failed

to

send,

Error:"

<<

WSAGetLastError()<<endl;

}

memset(SendBuf,

0,

1024);

}

if

(*ClientSocket

!=

INVALID_SOCKET)

{

closesocket(*ClientSocket);

}

return

0;

}

int

_tmain(int

argc,

_TCHAR*

argv[])

{

WSAData

wsd;

WSAStartup(MAKEWORD(2,

2),

&wsd);

SOCKET

ListenSocket

=

socket(AF_INET,

SOCK_STREAM,

0);

SOCKADDR_IN

ListenAddr;

ListenAddr.sin_family

=

AF_INET;

ListenAddr.sin_addr.S_un.S_addr

=

INADDR_ANY;//本機(jī)ip

ListenAddr.sin_port

=

htons(PORT);

//綁定監(jiān)聽端口

int

n;

n

=

bind(ListenSocket,

(LPSOCKADDR)&ListenAddr,

sizeof(ListenAddr));

if

(n

==

SOCKET_ERROR)

{

cout

<<

"failed

to

bind!"

<<

endl;

return

-1;

}

else

{

cout

<<

"bind

success

to:"

<<

PORT

<<

endl;

}

//開始監(jiān)聽

int

l

=

listen(ListenSocket,

MaxClient);

if

(l

==

0)

{

cout

<<

"server

ready,

wait

to

requirement..."

<<

endl;

}

else

{

cout

<<

"Error:"

<<

GetLastError()

<<

"listen

return"

<<

l

<<

endl;

}

while

(1)

{

//循環(huán)接收客戶端連接請求并創(chuàng)建服務(wù)線程

if(num

<

MaxClient)

{

SOCKET

*ClientSocket=new

SOCKET;

HANDLE

hThread;

int

SockAddrlen

=

sizeof(sockaddr);

*ClientSocket

=

accept(ListenSocket,

0,

0);

cout

<<

"client

"

<<

*ClientSocket

<<

"

has

connect

to

server"

<<

endl;

num++;

hThread

=

CreateThread(NULL,

NULL,

&SeverThread,

(LPVOID)ClientSocket,

0,

NULL);

CloseHandle(hThread);

}

else

{

cout

<<

"Max

Client!Please

wait

for

accept..."

<<

endl;

}

}

closesocket(ListenSocket);

WSACleanup();

return

0;

}在這個(gè)服務(wù)器端,每有一個(gè)新的客戶端請求建立連接,服務(wù)器都會(huì)新開一個(gè)線程為一個(gè)客戶端提供服務(wù),并在這個(gè)線程中新建立一個(gè)SOCKET用于與客戶端進(jìn)行通信,同時(shí)服務(wù)器也應(yīng)該能夠在不同階段(接收或發(fā)送)檢測客戶端是否已經(jīng)斷開連接,以便及時(shí)釋放資源。Client端#include

"stdafx.h"

#include<iostream>

#include<cstdio>

#include<string>

#include<Winsock2.h>

#pragma

comment(lib,"ws2_32.lib")

using

namespace

std;

const

int

PORT

=

8000;

#define

MaxBufSize

1024

#define

_CRT_SECURE_NO_WARINGS

int

_tmain(int

argc,

_TCHAR*

argv[])

{

WSADATA

wsd;

WSAStartup(MAKEWORD(2,

2),

&wsd);

SOCKET

SocketClient

=

socket(AF_INET,

SOCK_STREAM,

0);

SOCKADDR_IN

ClientAddr;

ClientAddr.sin_family

=

AF_INET;

ClientAddr.sin_addr.S_un.S_addr

=

inet_addr("127.0.0.1");

ClientAddr.sin_port

=

htons(PORT);

int

n

=

0;

n

=

connect(SocketClient,

(struct

sockaddr*)&ClientAddr,

sizeof(ClientAddr));

if

(n

==

SOCKET_ERROR)

{

cout

<<

"failed

to

connect"

<<

endl;

return

-1;

}

cout

<<

"success

to

connect

to

Server"

<<

endl;

char

info[1024];//數(shù)據(jù)輸入緩沖區(qū)

char

SendBuff[MaxBufSize];//發(fā)送數(shù)據(jù)緩沖區(qū)

char

RecvBuff[MaxBufSize];//接收數(shù)據(jù)緩沖區(qū)

while

(1)

{

cout

<<

"input

your

message:"

<<

endl;

scanf_s("%s",&info,MaxBufSize);

if

(info[0]

==

"")

break;

strcpy(SendBuff,

info);

memset(info,

0,

sizeof(info));

int

k

=

0;

k

=

send(SocketClient,

SendBuff,

sizeof(SendBuff),

0);

memset(SendBuff,

0,

sizeof(SendBuff));

if

(k

<

0)

{

cout

<<

WSAGetLastError()

<<

endl;

cout

<<

"failed

to

send"

<<

endl;

}

int

n

=

0;

n

=

recv(SocketClient,

RecvBuff,

sizeof(RecvBuff),

0);

if

(n>0)

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論