運行時,請先啟動服務(wù)器端

/**//*
* 服務(wù)器端
*/

#include <Winsock2.h>
#include <stdio.h>
#include <iostream.h>
#pragma comment(lib,"Ws2_32.lib")
SOCKET sockSvc;//服務(wù)器端socket
SOCKET sockConnect; //連接用的socket
DWORD WINAPI RecvData(LPVOID lpParameter); //接收線程的函數(shù)
int main()


{
WORD wVersionRequested;//定義socket1.1或者socket2.0
WSADATA wsaData; //定義裝載socket版本的變量
int err; //錯誤變量
wVersionRequested = MAKEWORD(2,2); //定義連接為socket2.0
err = WSAStartup(wVersionRequested, &wsaData); //裝載socket2.0支持
if(0 != err)//判斷是否裝載成功

{
return -1;
}

if(LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)//判斷版本號,是否和定義的一樣

{
WSACleanup(); //若出問題,卸載支持,并結(jié)束程序返回-1
return -1;
}
sockSvc = WSASocket(AF_INET,SOCK_STREAM,0,NULL,0,WSA_FLAG_OVERLAPPED);

/**//*
SOCKET WSASocket(int af, int type, int protocol,
LPWSAPROTOCOL_INFO lpprotocolinfo,
GROUP g, DWORD dwflags)

SOCKET socket(int af, int type, int protocol)
參數(shù):地址族,套接字類型和協(xié)議類型
這三個因素共同決定了創(chuàng)建套接字的服務(wù)提供者
傳輸服務(wù)提供者實現(xiàn)的功能包括建立連接,傳輸數(shù)據(jù),實現(xiàn)流控制和差錯控制等函數(shù)。
Ws2_32.dll在應(yīng)用程序和服務(wù)提供者之間實現(xiàn)了媒介的功能

第一
socket()和WSASocket()函數(shù)都能返回一個SOCKET套接字;
socket()主要實現(xiàn)同步傳輸,Socket庫中例程在應(yīng)用于阻塞套接口時會阻塞。
WSASocket()用于異步傳輸,WSASocket()的發(fā)送操作和接收操作都可以被重疊使用。
WSASocket()的接收函數(shù)可以被多次調(diào)用,發(fā)出接收緩沖區(qū),準(zhǔn)備接收到來的數(shù)據(jù)。
發(fā)送函數(shù)也可以被多次調(diào)用,組成一個發(fā)送緩沖區(qū)隊列。
socket()卻只能發(fā)過之后等待回消息才可做下一步操作!
其次
WSASocket()所支持的版本如下:
Version: Requires Windows Sockets2.0.
Header: Declared in Winsock2.h.
socket()所支持老一些的版本,如Windows Sockets1.0和
Version: Requires Windows Sockets1.1
*/
SOCKADDR_IN addrSvc; //服務(wù)器地址信息
addrSvc.sin_addr.S_un.S_addr = htonl(INADDR_ANY); //0 接收所有數(shù)據(jù)包
addrSvc.sin_family = AF_INET;
addrSvc.sin_port = htons(4000);//監(jiān)聽 端口
bind(sockSvc,(SOCKADDR*)&addrSvc,sizeof(SOCKADDR)); //綁定服務(wù)和端口
listen(sockSvc,50);

/**//*
int listen(SOCKET s, int users);
服務(wù)程序可以調(diào)用listen函數(shù)使其流套接字s處于監(jiān)聽狀態(tài)。處于監(jiān)聽狀態(tài)的流套接字s將維
護(hù)一個客戶連接請求隊列,該隊列最多容納users個客戶連接請求。假如該函數(shù)執(zhí)行成功,
則返回0;如果執(zhí)行失敗,則返回SOCKET_ERROR。
*/
SOCKADDR_IN addrClient;
int length = sizeof(SOCKADDR);
while(1)

{
sockConnect = accept(sockSvc, (SOCKADDR*)&addrClient,&length);

/**//*
SOCKET accept(
SOCKET s,
struct sockaddr FAR *addr,
int FAR *addrlen
);
服務(wù)程序調(diào)用accept函數(shù)從處于監(jiān)聽狀態(tài)的流套接字s的客戶連接請求隊列中取出排在最前的一個客戶請求,
并且創(chuàng)建一個新的套接字來與客戶套接字創(chuàng)建連接通道,如果連接成功,就返回新創(chuàng)建的套接字的描述符,
以后與客戶套接字交換數(shù)據(jù)的是新創(chuàng)建的套接字;如果失敗就返回 INVALID_SOCKET。該函數(shù)的第一個參數(shù)
指定處于監(jiān)聽狀態(tài)的流套接字;操作系統(tǒng)利用第二個參數(shù)來返回新創(chuàng)建的套接字的地址結(jié)構(gòu);操作系統(tǒng)利用
第三個參數(shù)來返回新創(chuàng)建的套接字的地址結(jié)構(gòu)的長度。
*/
if(INVALID_SOCKET != sockConnect)

{
HANDLE hThread;
hThread=CreateThread(NULL,0,RecvData,(LPVOID)sockConnect,0,NULL);

/**//*
/*
我們得定義一個句柄用來存放它的返回值。還定義一個指向線程ID的DWORD值dwThreadId。
CreateThread函數(shù)有六個參數(shù)分別是
LPSECURITY_ATTRIBUTES lpThreadAttributes, // pointer to security attributes
DWORD dwStackSize, // initial thread stack size
LPTHREAD_START_ROUTINE lpStartAddress, // pointer to thread function
LPVOID lpParameter, //argument for new thread
DWORD dwCreationFlags, // creation flags
LPDWORD lpThreadId // pointer to receive thread ID
中第一個參數(shù)我們設(shè)置為NULL,使這個句柄不能被繼承;第二個參數(shù)設(shè)置為0,使用默認(rèn)的堆棧
大小;第三個參數(shù)為線程函數(shù)的起始地址,也就是線程函數(shù)的函數(shù)名;第四個參數(shù)要傳遞給線程
函數(shù)的值;第五個參數(shù)為0,創(chuàng)建好之后馬上讓線程運行;第六個參數(shù)設(shè)置為指向線程ID的地址。
嚴(yán)格來說這里需要加錯誤檢測if(NULL == hThead){}
*/
CloseHandle(hThread);
}
}
Sleep(INFINITE);
closesocket(sockConnect);
WSACleanup(); // 嚴(yán)格來說這里需要加錯誤檢測if(0 != WSACleanup()){}
}
DWORD WINAPI RecvData(LPVOID lpParameter) //線程接收函數(shù)

{
SOCKET socket = (unsigned int)lpParameter;
char recvBuffer[1024];
for(;;)

{
//receive data from client
if(SOCKET_ERROR == recv(socket, recvBuffer, 1024, 0)) //和客戶端的send相對應(yīng)

{
cout<<"The receive data defeat or was the client side already withdraws
\n"<<endl;
break;
}
cout<<"Client says: "<<recvBuffer<<endl;
}
closesocket(socket); // 嚴(yán)格來說這里需要加錯誤檢測if(0 != closesocket(socket)){}
return 0;
}

/**//*
* 客戶端
*/

#include<Winsock2.h>
#include<stdio.h>
#pragma comment(lib,"Ws2_32.lib")

void main()


{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(2, 2);
err = WSAStartup(wVersionRequested, &wsaData);

if(err != 0)
{
return;
}
if(LOBYTE(wsaData.wVersion) != 2 ||

HIBYTE(wsaData.wVersion) != 2 )
{
WSACleanup();
return;
}

SOCKET sockClient = WSASocket(AF_INET,SOCK_STREAM,0,NULL,0,WSA_FLAG_OVERLAPPED);
SOCKADDR_IN addrClient; //服務(wù)器地址信息
addrClient.sin_addr.S_un.S_addr = inet_addr("192.168.94.37"); //要連接的服務(wù)地址
addrClient.sin_family = AF_INET; //協(xié)議族
addrClient.sin_port = htons(4000); //請求的端口
char sendBuffer[1024]; //每次發(fā)送的最大數(shù)據(jù)量
connect(sockClient, (SOCKADDR*)&addrClient, sizeof(SOCKADDR));//連接服務(wù)器端
while(true)

{

/**//*send data to service*/
printf("Please input data:\n");
if(gets(sendBuffer) == NULL) //輸入要發(fā)送的數(shù)據(jù)
break;
else

{
if(SOCKET_ERROR == send(sockClient,sendBuffer,
strlen(sendBuffer)+1,0)) //TCP方式發(fā)送

{
printf("Transmission data defeat!\n");
break;
}
}
}
closesocket(sockClient); // 嚴(yán)格來說這里需要加錯誤檢測if(0 != closesocket(socket)){}
WSACleanup();
}
地震讓大伙知道:居安思危,才是生存之道。