学了这么久的java,突然网络编程课设又得转回大一学的c和c++,真是脑壳都大了…还是记录一下先,顺便试着写一写博客,嘿嘿…
1.简单的socket应用–全双工聊天程序实现,工具–vs2017社区版
//运用子线程来实现全双工通信
//Service端
void sendinfo(SOCKET sockConn) {//子线程将要执行方法
while (1) {
if (flag) {//保证下面这句话只执行一遍
printf("%s has connected...\n", inet_ntop(AF_INET, (void*)&addrClient.sin_addr, sendd, 16)); //提示连接信息
flag = 0;
}
if (strcmp(gets_s(s, 50), "quit") == 0) {
//如果键入了quit,则向对方发送"对方已经终止聊天..."字符串,这样对方可以凭此结束
send(sockConn, "对方已经终止聊天...", strlen("对方已经终止聊天...quit") + 1, 0);
printf("%s has disconnected...\n", inet_ntop(AF_INET, (void*)&addrClient.sin_addr, sendd, 16)); //提示断开连接信息
closesocket(sockConn);//关闭套接字
return;//结束子线程
}
sprintf_s(sendBuf, s);
send(sockConn, sendBuf, strlen(sendBuf) + 1, 0);//发送消息
//清除缓存
memset(s, 0, sizeof(s) / sizeof(char));
memset(sendBuf, 0, sizeof(sendBuf) / sizeof(char));
memset(sendd, 0, sizeof(sendd) / sizeof(char));
}
}
int main()
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(1, 1);
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0) {
return 0;
}
if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1) {
WSACleanup();
return 0;
}
SOCKET sockSrv = socket(AF_INET, SOCK_STREAM, 0);
SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
addrSrv.sin_family = AF_INET;
addrSrv.sin_port = htons(6000);
bind(sockSrv, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));//将套接字绑定本地端口
listen(sockSrv, 5);//将套接字设为监听模式
int len = sizeof(SOCKADDR);
//如果监听的客户队列里有客户发起连接请求,accept进行接受,第二个参数为一个可识别客户端实体,
//该方法返回一个新socket,之后和该客户进行交互的即为该socket
SOCKET sockConn = accept(sockSrv, (SOCKADDR*)&addrClient, &len);
std::thread t(sendinfo, sockConn);//创建子线程发送消息
t.detach();
while (1) {
int ret = recv(sockConn, recvBuf, 50, 0);//接受Client消息
if (ret <= 0)
return 0;
printf("Client(%s):%s\n", inet_ntop(AF_INET, (void*)&addrClient.sin_addr, sendd, 16), recvBuf);//打印
if (strcmp(recvBuf, "对方已经终止聊天...") == 0) {//如果接受到此语句,退出循环,准备结束
break;
}
memset(recvBuf, 0, sizeof(recvBuf) / sizeof(char));//清空缓存
}
//结束套接字
closesocket(sockConn);
closesocket(sockSrv);
WSACleanup();
printf("press enter to continue...\n");
getchar();
return 0;
}
//Client端,也是利用子线程实现全双工通信
void sendINFO(SOCKET sockClient) {//子线程执行的方法
while (1) {
if (flag) {
printf("you have connected...\n"); //提示连接信息
flag = 0;//避免循环打印上面这句话
}
if (strcmp(gets_s(s, 50), "quit") == 0) {
send(sockClient, "对方已经终止聊天...", strlen("对方已经终止聊天...") + 1, 0);
printf("you have disconnected...\n"); //提示连接信息
closesocket(sockClient);//关闭连接套接字
return;//退出
}
send(sockClient, s, strlen(s) + 1, 0);//发送消息
memset(s, 0, sizeof(s) / sizeof(char));//清除缓存区
}
}
int main()
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(1, 1);
err = WSAStartup(wVersionRequested, &wsaData);//初始化网络环境
if (err != 0) {
return 0;
}
if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1) {
WSACleanup();
return 0;
}
inet_pton(AF_INET, "10.1.11.244", (void*)&addrSrv.sin_addr.S_un.S_addr);//64位的机器用这个方法,IP是Service的IP,需自行修改
//addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");//参考代码中的老古董方法
addrSrv.sin_family = AF_INET;
addrSrv.sin_port = htons(6000);
SOCKET sockClient = socket(AF_INET, SOCK_STREAM, 0);//建立socket
connect(sockClient, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));//建立套接字连接
std::thread t1(sendINFO, sockClient);//创建子线程发送信息
t1.detach();
while (1) {
int ret = recv(sockClient, recvBuf, 50, 0);//接受信息
if (ret <= 0)//接受信息失败(对面关闭连接等于0或者SOCKET_ERROR=-1)结束
return 0;
printf("Service:%s\n", recvBuf);//打印
if (strcmp(recvBuf, "对方已经终止聊天...") == 0) {//如果对面终止,此线程需退出
break;
}
memset(recvBuf, 0, sizeof(recvBuf) / sizeof(char));//清除缓存区
}
closesocket(sockClient);//关闭套接字连接
WSACleanup();
printf("press enter to continue...\n");
getchar();
return 0;
}
第一次写博客,有点小鸡冻,嘿嘿…欢迎指正错误