用Socket实现聊天系统,前提加入加入静态库:
#pragma comment(lib,"ws2_32.lib")
1.加载套接字库,确定socket的版本;
WSAStartup():初始化sock套接字
2.创建套接字,用于监听;
socket(AF_INET,SOCK_DGRAM,0);
1)AF_INET=PF_INET;地址族
2)参数意思:Internet协议,socket类型
3)流式套接字(SOCK_STREAM):用到的协议TCP
4)数据报套接字(SOCK_DGRAM): 无连接的、不可靠的UDP
5)与地址族相关的协议:为0
3.绑定套接字;
4.将套接字设为监听模式:listen()
1)套接字描述符
2)等待链接队列的最大长度
5.接收客户端链接请求:accept();
1)参数信息:
2)sockSrv:已经设置为监听状态的套接字
6.打印接收到的数据;
printf();
7.发送数据
1)TCP协议: send() recv()
2)UDP协议: sendto() recvfrom()
8.关闭套接字库;
1) closesocket(sockClient);
2) WSACleanup();
客户端实现:
#include
#include
#include
#include
using namespace std;
#pragma comment(lib,"ws2_32.lib")
int main()
{
printf("请输入对方IP地址\n");
char szDestIP[16];//192.168.100.100
scanf("%s",szDestIP);
//加载套接字库,确定socket的版本;
//typedef unsigned short WORD;
//typedef WSAData WSADATA;
WORD wVersionRequested;
wVersionRequested=MAKEWORD(2,2);
WSADATA wsaData; //实际加载的套接字版本保存在wsData
//WSAStartup():初始化sock套接字
int nErr=WSAStartup(wVersionRequested,&wsaData);
if(nErr!=0)
{
printf("加载套接字库失败\n");
return 0;
}
//LOBYTE是一个宏 ,低位字节||高位字节
//wsaData.wVersion:实际加载的版本号
if(LOBYTE(wsaData.wVersion)!=2 || HIBYTE(wsaData.wVersion)!=2)
{
printf("加载套接字库不一致\n");
WSACleanup();
return 0;
}
//创建套接字,用于监听;
SOCKET sockClient=socket(AF_INET,SOCK_DGRAM,0);
SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr=inet_addr(szDestIP);
addrSrv.sin_family=AF_INET; //使用INET协议
addrSrv.sin_port=htons(9880);//指定端口号
char szRecvBuf[200];
char szSendBuf[200];
int nlength=sizeof(SOCKADDR);
while(TRUE)
{
//输入消息
printf("请输入待发送消息:\n");
scanf("%s",szSendBuf);
//发送消息
//TCP协议: send() recv()
//UDP协议: sendto() recvfrom()
sendto(sockClient,szSendBuf,strlen(szSendBuf)+1,0,(SOCKADDR*)&addrSrv,nlength);
//等待接收数据
recvfrom(sockClient,szRecvBuf,200,0,(SOCKADDR*)&addrSrv,&nlength ); //接收数据,会阻塞
if('q'==szRecvBuf[0])
{
sendto(sockClient,"q",strlen("q")+1,0,(SOCKADDR*)&addrSrv,nlength);
printf("聊天结束\n");
break;
}
//打印接收到的数据
printf("%s 说:%s\n",inet_ntoa(addrSrv.sin_addr),szRecvBuf);
}
//关闭套接字库
closesocket(sockClient);
WSACleanup();
system("pause");
return 0;
}
服务端实现:
#include
#include
#include
#include
#include
using namespace std;
#pragma comment(lib,"ws2_32.lib")
int main()
{
//加载套接字库,确定socket的版本;
//typedef unsigned short WORD;
//typedef WSAData WSADATA;
WORD wVersionRequested;
wVersionRequested=MAKEWORD(2,2);
WSADATA wsaData; //实际加载的套接字版本保存在wsData
//WSAStartup:初始化sock套接字
int nErr=WSAStartup(wVersionRequested,&wsaData);
if(nErr!=0)
{
printf("加载套接字库失败\n");
return 0;
}
//LOBYTE是一个宏 ,低位字节||高位字节
//wsaData.wVersion:实际加载的版本号
if(LOBYTE(wsaData.wVersion)!=2 || HIBYTE(wsaData.wVersion)!=2)
{
printf("加载套接字库不一致\n");
WSACleanup(); //
return 0;
}
//创建套接字,用于监听;
//AF_INET=PF_INET;地址族
//参数意思:Internet协议,socket类型
//流式套接字(SOCK_STREAM):用到的协议TCP
//数据报套接字(SOCK_DGRAM): 无连接的、不可靠的UDP
//与地址族相关的协议:为0
SOCKET sockSrv=socket(AF_INET,SOCK_DGRAM,0);
SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
//htonl()将主机顺序转换为网络字节顺序
addrSrv.sin_family=AF_INET; //使用INET协议
addrSrv.sin_port=htons(9880);//指定端口号
char szRecvBuf[200];
char szSendBuf[200];
//绑定套接字
//sockSrv :要绑定的套接字;
//addrSrv:套接字的本地地址信息;
//sizeof(SOCKADDR):地址结构体的大小;
if(SOCKET_ERROR==bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR)))
{
printf("绑定套接字失败\n");
return 0;
}
SOCKADDR_IN addrClient;
int nlength=sizeof(SOCKADDR);
while(TRUE)
{
recvfrom(sockSrv,szRecvBuf,200,0,(SOCKADDR*)&addrClient,&nlength ); //接收数据,会阻塞
if('q'==szRecvBuf[0])
{
sendto(sockSrv,"q",strlen("q")+1,0,(SOCKADDR*)&addrClient,nlength);
printf("聊天结束\n");
break;
}
//打印接收到的数据
printf("%s 说 %s\n",inet_ntoa(addrClient.sin_addr),szRecvBuf);
//发送数据
printf("请输入待发送信息:\n");
scanf("%s",szSendBuf);
sendto(sockSrv,szSendBuf,strlen(szSendBuf)+1,0,(SOCKADDR*)&addrClient,nlength); //发送数据
}
//关闭套接字库
closesocket(sockSrv);
WSACleanup();
system("pause");
return 0;
}
改成发布型(release)的;