1 . WSAStartup函數:該函數用於初始化Ws2_32.dll動態連接庫,在使用socket以前,必定要初始化該連接庫。
初始化:css
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData)//第一個參數表示winsock的版本,本例使用的是winsock2.2版本。
2 . socket函數,建立一個socketios
//af:一個地址家族,一般爲AF_INET
//type:套接字類型,SOCK_STREAM表示建立面向流鏈接的套接字。爲SOCK_DGRAM,表示建立面向無鏈接的數據包套接字。爲SOCK_RAW,表示建立原始套接字
//protocol:套接字所用協議,不指定能夠設置爲0
//返回值就是一個socket
SOCKET socket(int af,int type,int protocol);
3 . bind函數:該函數用於將套接字綁定到指定的端口和地址。
第一個參數爲socket,第二個參數是一個結構指針,它包含了端口和IP地址信息,第三個參數表示緩衝區長度。須要說明的是,第二個參數在API中表示爲:const struct sockaddr FAR*,這個語法結構我還沒見過,網上說這是遠指針,win16時期的產物,算是長見識了。web
SOCKADDR_IN addrSrv;
addrSrv.sin_family = AF_INET;
addrSrv.sin_port = htons(8888); //1024以上的端口號
addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);//IP地址
bind(sockSrv, (LPSOCKADDR)&addrSrv, sizeof(SOCKADDR_IN));
4 . listen函數:將socket設置爲監聽模式,服務端的socket特有。必須將服務端的socket設置爲監聽模式才能和服務端簡歷鏈接。
裏面有兩個參數,第一個參數爲socket,第二個參數爲等待鏈接最大隊列的長度。編程
listen(sockSrv,10)
5 . accept函數:服務端socket接收客戶端的鏈接請求,鏈接成功,則返回一個socket,該socket能夠在服務端發送和接收數據。第一個參數爲socket,第二個參數爲包含客戶端端口IP信息的sockaddr_in結構指針,第三個參數爲接收參數addr的長度。windows
int len = sizeof(SOCKADDR);
accept(sockSrv, (SOCKADDR *) &addrClient, &len);
6 . closesocket函數:關閉socket,裏面的惟一的一個參數就是要關閉的socket。
7 . connect函數:客戶端socket發送鏈接請求的函數,第一個參數是客戶端的socket,第二個參數是一個結構體指針,裏面包括鏈接主機的地址和ip,第三個參數爲緩衝區的長度。api
connect(sockClient, (struct sockaddr*)&addrSrv, sizeof(addrSrv));
8 . htons函數:將一個16位無符號短整型數據由主機排列方式轉化爲網絡排列方式,htonl函數的做用剛好相反。
9 . recv函數:接收數據,第一個參數爲socket,第二個參數爲接收數據緩衝區,第三個參數爲緩衝區的長度,第四個參數爲函數的調用方式。服務器
char buff[1024];
recv(sockClient, buff, sizeof(buff), 0);
10 . send函數:發送數據,裏面的參數基本和recv()同樣。網絡
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include "winsock2.h"
#include<cstdlib>
#pragma comment(lib,"ws2_32.lib")//引用庫文件
using namespace std;
char recvBuf[100];
SOCKET sockConn;
/** * 在一個新的線程裏面接收數據 */
DWORD WINAPI Fun(LPVOID lpParamter)
{
while(true){
memset(recvBuf, 0, sizeof(recvBuf));
// //接收數據
recv(sockConn, recvBuf, sizeof(recvBuf), 0);
printf("%s\n", recvBuf);
}
closesocket(sockConn);
}
int main()
{
WSADATA wsaData;
int port = 8888;//端口號
if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
printf("初始化失敗");
return 0;
}
//建立用於監聽的套接字,即服務端的套接字
SOCKET sockSrv = socket(AF_INET, SOCK_STREAM, 0);
SOCKADDR_IN addrSrv;
addrSrv.sin_family = AF_INET;
addrSrv.sin_port = htons(port); //1024以上的端口號
/** * INADDR_ANY就是指定地址爲0.0.0.0的地址,這個地址事實上表示不肯定地址,或「全部地址」、「任意地址」。 通常來講,在各個系統中均定義成爲0值。 */
addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
int retVal = bind(sockSrv, (LPSOCKADDR)&addrSrv, sizeof(SOCKADDR_IN));
if(retVal == SOCKET_ERROR){
printf("鏈接失敗:%d\n", WSAGetLastError());
return 0;
}
if(listen(sockSrv,10) ==SOCKET_ERROR){
printf("監聽失敗:%d", WSAGetLastError());
return 0;
}
SOCKADDR_IN addrClient;
int len = sizeof(SOCKADDR);
while(1)
{
//等待客戶請求到來
sockConn = accept(sockSrv, (SOCKADDR *) &addrClient, &len);
if(sockConn == SOCKET_ERROR){
printf("等待請求失敗:%d", WSAGetLastError());
break;
}
printf("客戶端的IP是:[%s]\n", inet_ntoa(addrClient.sin_addr));
//發送數據
char sendbuf[] = "你好,我是服務端,我們一塊兒聊天吧";
int iSend = send(sockConn, sendbuf, sizeof(sendbuf) , 0);
if(iSend == SOCKET_ERROR){
printf("發送失敗");
break;
}
HANDLE hThread = CreateThread(NULL, 0, Fun, NULL, 0, NULL);
CloseHandle(hThread);
}
closesocket(sockSrv);
WSACleanup();
system("pause");
return 0;
}
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include "winsock2.h"
#pragma comment(lib,"ws2_32.lib")//引用庫文件
using namespace std;
int main()
{
//加載套接字
WSADATA wsaData;
char buff[1024];
memset(buff, 0, sizeof(buff));
if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
printf("初始化Winsock失敗");
return 0 ;
}
SOCKADDR_IN addrSrv;
addrSrv.sin_family = AF_INET;
addrSrv.sin_port = htons(8888);//端口號
addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");//IP地址
//建立套接字
SOCKET sockClient = socket(AF_INET, SOCK_STREAM, 0);
if(SOCKET_ERROR == sockClient){
printf("Socket() error:%d", WSAGetLastError());
return 0;
}
//向服務器發出鏈接請求
if(connect(sockClient, (struct sockaddr*)&addrSrv, sizeof(addrSrv)) == INVALID_SOCKET){
printf("鏈接失敗:%d", WSAGetLastError());
return 0;
}else
{
//接收數據
recv(sockClient, buff, sizeof(buff), 0);
printf("%s\n", buff);
}
//發送數據
char buffs[] = "下面我們開始聊天了";
send(sockClient, buffs, sizeof(buffs), 0);
//不斷輸入,而後發送
while(true){
cin>>buffs;
send(sockClient, buffs, sizeof(buffs), 0);
}
//關閉套接字
closesocket(sockClient);
WSACleanup();//釋放初始化Ws2_32.dll所分配的資源。
system("pause");//讓屏幕暫留
return 0;
}
效果圖:
eclipse
有一個小問題就是使用cin輸入漢字的時候,偶爾會發生接收過程當中發生錯誤的現象。
我是在eclipse下寫得代碼,加載庫文件在eclipse下的配置請戳這裏:
加載庫文件在eclipse下的配置連接
關於打開窗口,只需打開項目目錄下debug文件下的對應的.exe文件便可打開窗口。使用eclipse下的控制檯連個程序並很差使。
最後,本篇文章的代碼參考了下面的博客:
博客地址
感謝分享!socket