一个简单的聊天服务器端程序,多线程设计,针对多客户端。windows平台
服务器:
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <iostream>
using namespace std;
#pragma comment(lib, "ws2_32.lib")
//一个简单的聊天程序 针对多客户端
//stdcall 的线程处理函数
DWORD WINAPI ThreadFun(LPVOID lpThreadParameter);
int main() {
//加载winsock2的环境
WSADATA wd;
if(0 != WSAStartup(MAKEWORD(2, 2), &wd)) {
cout << "WSAStartup error : " << GetLastError() << endl;
return 0;
}
//1. 创建流式套接字
SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(INVALID_SOCKET == s) {
cout << "socket error : " << GetLastError() << endl;
return 0;
}
//2. 绑定端口和Ip
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(8891);
inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr);//ip地址转网络字节序
int len = sizeof(sockaddr_in);
if(SOCKET_ERROR == bind(s, (SOCKADDR*)&addr, len)) {
cout << "bind error : " << GetLastError() << endl;
return 0;
}
//3. 监听
listen(s, 5);
//主线程循环接收客户端的链接
while(true) {
sockaddr_in addrClient;
len = sizeof(sockaddr_in);
//4. 接收成功返回与client通讯的socket
SOCKET c = accept(s, (SOCKADDR*)&addrClient, &len);
if(INVALID_SOCKET != c) {
//创建线程 并且传入与client通讯的套接字
HANDLE hThread = CreateThread(NULL, 0, ThreadFun, (LPVOID)c, 0, NULL);
CloseHandle(hThread); //关闭对线程的引用
}
}
//6. 关闭监听套接字
closesocket(s);
//清理winsock2的环境
WSACleanup();
return 0;
}
DWORD WINAPI ThreadFun(LPVOID lpThreadParameter) {
//5. 与客户端通讯 发送或者接收数据
SOCKET c = (SOCKET) lpThreadParameter;
cout << "欢迎" << c << "进入聊天室!"<< endl;
//发送数据
char buf[100] = {0};
sprintf_s(buf, "欢迎%d 进入聊天室!", c);
send(c, buf, 100, 0);
//循环接收客户端数据
int ret = 0;
do
{
char buf[100] = {0};
ret = recv(c, buf, 100, 0);
cout << c << " 说: " << buf << endl;
} while (ret != SOCKET_ERROR && ret != 0);
cout << c << "离开了聊天室!" << endl;
return 0;
}
客户端:
#include <winsock2.h>//winsock2的头文件
#include <WS2tcpip.h>
#include <iostream>
using namespace std;
//勿忘,链接dll的lib
#pragma comment(lib, "ws2_32.lib")
int main() {
//加载winsock2的环境
WSADATA wd;
if(WSAStartup(MAKEWORD(2, 2), &wd) != 0) {
cout << "WSAStartup error:" << GetLastError() << endl;
return 0;
}
//1.创建流式套接字
SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(s == INVALID_SOCKET) {
cout << "socket error:" << GetLastError() << endl;
return 0;
}
//2.链接服务器
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(8891);
inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr);//ip地址转网络字节序
int len = sizeof(sockaddr_in);
if(connect(s, (SOCKADDR*)&addr, len) == SOCKET_ERROR) {
cout << "connect error:" << GetLastError() << endl;
return 0;
}
//3接收服务端的消息
char buf[100] = { 0 };
recv(s, buf, 100, 0);
cout << buf << endl;
//3随时给服务端发消息
int ret = 0;
do {
char buf[100] = { 0 };
cout << "请输入聊天内容:";
cin >> buf;
ret = send(s, buf, 100, 0);
} while(ret != SOCKET_ERROR&& ret != 0);
//4.关闭监听套接字
closesocket(s);
//清理winsock2的环境
WSACleanup();
return 0;
}