暂时先放下代码 存下 自己写得有很多得不足
unix 网络编程 自己实现的应该TCP 长连接的 聊天室。。。。。。。。 肯定有很多不足 和写的不好的地方见谅 这里只是我作为入门的一个开始练手
后续 看书 我会慢慢完善的 这里先放下代码
2020/7/8 22:56 更 留言 准备下班了 要努力学习啊
7/9答二 发现代码服务端贴错了
服务端代码
#include
#include
#include
// #pragma comment(lib, "ws2_32.lib")
#define PORT 9527
#define IP "127.0.0.1"
int g_ServerFd;
struct sockaddr_in g_Servaddr;
socklen_t g_ServaddrLen;
std::list<int> g_ClientList; //用list来存放套接字,没有限制套接字的容量就可以实现一个server跟若干个client通信
void getConn() {
while (1) {
int conn = accept(g_ServerFd, (struct sockaddr *)&g_Servaddr, &g_ServaddrLen);
g_ClientList.push_back(conn);
printf("创建新连入client的文件符 %d \n", conn);
}
}
void sendMsg() {
while(1) {
char buf[1024];
fgets(buf, sizeof(buf), stdin);
for (auto it = g_ClientList.begin(); it != g_ClientList.end(); ++it)
send(*it, buf, sizeof(buf), 0);
}
}
void getMsg() {
struct timeval tv;
tv.tv_sec = 0.1; //设置倒计时时间
tv.tv_usec = 0;
while (1) {
for (auto it = g_ClientList.begin(); it != g_ClientList.end(); ++it) {
fd_set rfds;
FD_ZERO(&rfds);
int maxfd = 0;
int retval = 0;
FD_SET(*it, &rfds);
if (maxfd < *it) maxfd = *it;
retval = select(maxfd + 1, &rfds, NULL, NULL, &tv);
if (retval == -1) {
printf("select error\n");
}
else if (retval == 0) {
//pass
}
else {
char buf[1024];
memset(buf, 0, sizeof(buf));
int len = recv(*it, buf, sizeof(buf), 0);
printf("%s", buf);
for(auto i : g_ClientList) {
if(i != *it) send(i, buf, sizeof(buf), 0);
}
}
}
Sleep(1);
}
}
void init() {
WORD sockVersion = MAKEWORD(2, 2);
WSADATA wsaData;
if (WSAStartup(sockVersion, &wsaData) != 0) //通过一个进程初始化ws2_32.dll
{
std::cout << "Initialize WSA failed" << std::endl;
exit(1);
} // window 得 这样 linux 下 库全 没这么麻烦
g_ServerFd = socket(AF_INET, SOCK_STREAM, 0);
memset(&g_Servaddr, 0, sizeof(g_Servaddr));
g_Servaddr.sin_family = AF_INET;
g_Servaddr.sin_port = htons(PORT);
g_Servaddr.sin_addr.s_addr = inet_addr(IP);
if (bind(g_ServerFd, (struct sockaddr *)&g_Servaddr, sizeof(g_Servaddr)) == -1) {
perror("bind");
exit(1);
}
if (listen(g_ServerFd, 200) == -1) {
perror("listen");
exit(1);
}
g_ServaddrLen = sizeof(g_Servaddr);
std::thread t(getConn);
t.detach(); //detach的话后面的线程不同等前面的进程完成后才能进行,如果这里改为join则前面的线程无法判断结束,就会等待
std::thread t1(sendMsg);
t1.detach();
std::thread t2(getMsg);
t2.detach();
}
int main() {
init();
while(1);
return 0;
}
客户端代码:
#include
#include
#include
#define MYPORT 9527
#define BUFFER_SIZE 1024
int g_ClientFD;
fd_set ReadFd;
struct sockaddr_in g_Servaddr;
int retval, maxfd;
void sendMsg() {
while (1) {
char buf[1024];
fgets(buf, sizeof(buf), stdin);
send(g_ClientFD, buf, sizeof(buf), 0);
}
}
void init() {
WORD sockVersion = MAKEWORD(2, 2);
WSADATA wsaData;
if (WSAStartup(sockVersion, &wsaData) != 0) //通过一个进程初始化ws2_32.dll
{
std::cout << "Initialize WSA failed" << std::endl;
exit(0);
}
g_ClientFD = socket(AF_INET, SOCK_STREAM, 0);
memset(&g_Servaddr, 0, sizeof(g_Servaddr));
g_Servaddr.sin_family = AF_INET;
g_Servaddr.sin_port = htons(MYPORT); ///服务器端口
g_Servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); ///服务器ip
if (connect(g_ClientFD, (struct sockaddr *)&g_Servaddr, sizeof(g_Servaddr)) == -1)
{
perror("connect");
exit(1);
}
}
void run() {
std::thread t(sendMsg); // 读取是单独的一个线程
t.detach();
struct timeval tv;
tv.tv_sec = 0.1;
tv.tv_usec = 0;
while (1) {
/*把可读文件描述符的集合清空*/
FD_ZERO(&ReadFd);
FD_SET(g_ClientFD, &ReadFd);
maxfd = 0;
/*把当前连接的文件描述符加入到集合中*/
if(maxfd < g_ClientFD) maxfd = g_ClientFD;
retval = select(maxfd + 1, &ReadFd, NULL, NULL, &tv);
if (retval == -1) {
printf("select出错,客户端程序退出\n");
exit(0);
} else if (retval == 0){
//pass
} else {
/*服务器发来了消息*/
if (FD_ISSET(g_ClientFD, &ReadFd)) {
char recvbuf[BUFFER_SIZE];
int len;
len = recv(g_ClientFD, recvbuf, sizeof(recvbuf), 0);
printf("%s", recvbuf);
memset(recvbuf, 0, sizeof(recvbuf));
}
}
}
}
int main()
{
init();
run();
while(1);
return 0;
}