编译器:Vs2013 community (VC6.0 运行亦可,但要注意函数的更新,如更安全的函数,etc)
服务器端程序流程:
1、加载套接字库
2、创建套接字(socket)。
3、将套接字绑定到一个本地地址和端口上(bind)。
4、将套接字设为监听模式,准备接收客户请求(listen)。
5、等待客户请求到来;当请求到来后,接受连接请求,返回一个新的对应于此次连接的套接字(accept)。
6、用返回的套接字和客户端进行通信(send/recv)。
7、返回,等待另一客户请求。
8、关闭套接字。
客户端程序流程:
1、加载套接字库
2、创建套接字(socket)。
3、向服务器发出连接请求(connect)。
4、和服务器端进行通信(send/recv)。
5、关闭套接字。
服务器端代码:
#include <Winsock2.h>
#include <stdio.h>
void main()
{
/***********加载套接字库2.2版本************/
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(2, 2);
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0) {
return;
}
if (LOBYTE(wsaData.wVersion) != 2 ||
HIBYTE(wsaData.wVersion) != 2) {
WSACleanup();
return;
}
/******************创建套接字*******************/
SOCKET sockSrv = socket(AF_INET, SOCK_STREAM, 0);
/*****************绑定套接字********************/
SOCKADDR_IN addrSrv; //定义 地址结构体 变量addrSrv
addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
addrSrv.sin_family = AF_INET;
addrSrv.sin_port = htons(6800);
bind(sockSrv, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));
/****************设置监听模式********************/
listen(sockSrv, 5);//参数2:等待连接队列的最大值
char recvBuf[100];
char sendBuf[100];
char tempBuf[200];
/***********等待客户连接请求到来,并接受**********/
SOCKADDR_IN addrClient;
int len = sizeof(SOCKADDR);
SOCKET sockConn = accept(sockSrv, (SOCKADDR*)&addrClient, &len);
while (1)
{
/**********进行通信**********/
recv(sockConn, recvBuf, 100, 0); //服务端先接收数据
if ('~' == recvBuf[0])//如果接受的数据第一个字符是 ~ 则退出!!!
{
send(sockConn, "~", strlen("~") + 1, 0);
printf("Chat end!\n");
break;
}
sprintf(tempBuf, "%s say %s.", inet_ntoa(addrClient.sin_addr), recvBuf);//将得到的数据格式化 放到tempBuf中
printf("%s\n", tempBuf);//输出客户端信息
printf("Server say: ");
gets(sendBuf);//从标准输入流中获取一行数据,回车后放入sendBuf中
send(sockConn, sendBuf, strlen(sendBuf) + 1, 0);
}
closesocket(sockSrv);//关闭套接字
WSACleanup();//终止对套接字库的使用
}
客户端代码:
#include <Winsock2.h>
#include <stdio.h>
void main()
{
/***********加载套接字库2.2版本************/
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(2, 2);
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0) {
return;
}
if (LOBYTE(wsaData.wVersion) != 2 ||
HIBYTE(wsaData.wVersion) != 2) {
WSACleanup();
return;
}
/******************创建套接字*******************/
SOCKET sockClient = socket(AF_INET, SOCK_STREAM, 0);
/************向服务器发出connect请求**************/
SOCKADDR_IN addrSrv;
// addrSrv.sin_addr.S_un.S_addr = inet_addr("192.168.1.111");
addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");//将点分十进制转换成ulong类型
addrSrv.sin_family = AF_INET;
addrSrv.sin_port = htons(6800);
connect(sockClient, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));
char recvBuf[100];
char sendBuf[100];
char tempBuf[200];
/************和服务器进行通信**********/
int len = sizeof(SOCKADDR);
while (1)
{
printf("Client say: ");
gets(sendBuf);//通过键盘得到一行数据
send(sockClient, sendBuf, strlen(sendBuf) + 1, 0);//客户端发送数据
recv(sockClient, recvBuf, 100, 0);//接收数据
if ('~' == recvBuf[0])
{
send(sockClient, "~", strlen("~") + 1, 0);
printf("Chat end!\n");
break;
}
sprintf(tempBuf, "%s say %s.", inet_ntoa(addrSrv.sin_addr), recvBuf);
printf("%s\n", tempBuf);
}
closesocket(sockClient);//关闭套接字
WSACleanup();//终止对套接字库的使用
}
注意事项:(我走过的弯路!!!)
1、在服务、客户两端,project->设置->linker,增加ws2_32.lib库
2、可以取消SDL检查(根据编译器不同自行选择)
3、服务端用于接收客户端数据的套接字sockConn要在while循环外
4、用于监听的套接字sockSrv与接收数据的套接字sockConn不同
运行效果图: