网络编程
基于TCP的Socket编程
服务器端流程
- 创建套接字(socket)
- 将套接字绑定到一个本地地址和端口上(bind)
- 将套接字设为监听模式,准备接收客户端的请求(listen)
- 等待客户端的请求,当请求到来时,接受连接请求,返回一个新的对应于此次连接的套接字(accept)
- 用返回的套接字和客户端进行通信(send/recv)
- 返回,等待另一客户请求
- 关闭套接字(closesocket)
客户端流程
- 创建套接字(socket)
- 向服务器端发出连接请求(connect)
- 和服务器端进行通信(send/recv)
- 关闭套接字(closesocket)
服务器端示例代码
(服务器和客户端工程都需要在工程->设置->链接里加上 ws2_32.lib动态链接库,才能加载winsocket套接字库)
#include<Winsock2.h>
#include<stdio.h>
void main(){
//加载套接字库
WORD mVersionRequest;
WSADATA wsaData;
int err;
mVersionRequest = MAKEWORD(1,1);
err = WSAStartup(mVersionRequest,&wsaData);
if(err != 0){
return;
}
if(LOBYTE(wsaData.wVersion)!=1 ||
HIBYTE(wsaData.wVersion)!=1){
WSACleanup();
return;
}
//创建套接字
SOCKET socketSrv = socket(AF_INET,SOCK_STREAM,0);//套接字的类型:SOCK_STREAM(流式套接字,基于TCP)
//绑定
SOCKADDR_IN addSrv;
addSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);//IP地址,INADDR_ANY代表任一ip,htonl表示将IP地址转化为网络字节顺序的IP地址格式(即高存位),htonl的参数是long类型,htons的参数是short类型
addSrv.sin_family = AF_INET;
addSrv.sin_port = htons(6000);//端口号
bind(socketSrv,(SOCKADDR*)&addSrv,sizeof(SOCKADDR));
//监听
listen(socketSrv,5);//5表示监听的缓冲区的最大数
SOCKADDR_IN addClient;
int len = sizeof(SOCKADDR);//必须要赋初值
while(1){
//接收客户端的请求
SOCKET socketClient = accept(socketSrv,(SOCKADDR*)&addClient,&len);
//向客户端发送欢迎语句
char sendBuff[100];
sprintf(sendBuff,"welcome %s\n",inet_ntoa(addClient.sin_addr));//格式化向客户端发送的字符串,inet_ntoa将地址转化成十进制点划分格式的IP地址
send(socketClient,sendBuff,strlen(sendBuff)+1,0);//发送长度多加一位,方便接收端加上结束字符
//接收客户端的数据
char recvBuff[100];
recv(socketClient,recvBuff,100,0);
printf("%s\n",recvBuff);
closesocket(socketClient);
}
// closesocket(socketSrv);
// WSACleanup();
}
客户端示例代码
#include<stdio.h>
#include<Winsock2.h>
void main(){
//加载套接字库
WORD mVersionRequest;
WSADATA wsaData;
int err;
mVersionRequest = MAKEWORD(1,1);
err = WSAStartup(mVersionRequest,&wsaData);
if(err != 0){
return;
}
if(LOBYTE(wsaData.wVersion)!=1 ||
HIBYTE(wsaData.wVersion)!=1){
WSACleanup();
return;
}
//创建套接字
SOCKET socketSrv = socket(AF_INET,SOCK_STREAM,0);
//建立连接
SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
addrSrv.sin_family = AF_INET;
addrSrv.sin_port = htons(6000);
connect(socketSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));
//接收数据
char recvBuff[100];
recv(socketSrv,recvBuff,100,0);
printf("%s\n",recvBuff);
//发送数据
char sendBuff[100];
printf("%s\n","please input data");
gets(sendBuff);
send(socketSrv,sendBuff,strlen(sendBuff)+1,0);
closesocket(socketSrv);
WSACleanup();
}`
基于UDP的Socket编程
服务器端流程
- 创建套接字(socket)
- 将套接字绑定到一个本地地址和端口上(bind)
- 等待接收数据(recvfrom)
- 关闭套接字(closesocket)
客户端流程
- 创建套接字(socket)
- 向服务器端发送数据(sendto)
- 关闭套接字(closesocket)
服务器端示例代码
#include<Winsock2.h>
#include<stdio.h>
void main(){
//加载套接字库
WORD mVersionRequest;
WSADATA wsaData;
int err;
mVersionRequest = MAKEWORD(1,1);
err = WSAStartup(mVersionRequest,&wsaData);
if(err != 0){
return;
}
if(LOBYTE(wsaData.wVersion)!=1 ||
HIBYTE(wsaData.wVersion)!=1){
WSACleanup();
return;
}
//创建套接字
SOCKET socketSrv = socket(AF_INET,SOCK_DGRAM,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(socketSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));
//接收
SOCKADDR_IN addrClient;
int len = sizeof(SOCKADDR);
char recvBuff[100];
recvfrom(socketSrv,recvBuff,100,0,(SOCKADDR*)&addrClient,&len);
printf("%s\n",recvBuff);
closesocket(socketSrv);
WSACleanup;
}
客户端示例代码
#include<Winsock2.h>
#include<stdio.h>
void main(){
//加载套接字库
WORD mVersionRequest;
WSADATA wsaData;
int err;
mVersionRequest = MAKEWORD(1,1);
err = WSAStartup(mVersionRequest,&wsaData);
if(err != 0){
return;
}
if(LOBYTE(wsaData.wVersion)!=1 ||
HIBYTE(wsaData.wVersion)!=1){
WSACleanup();
return;
}
//创建套接字
SOCKET socketSrv = socket(AF_INET,SOCK_DGRAM,0);
SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
addrSrv.sin_family = AF_INET;
addrSrv.sin_port = htons(6000);
//发送
char sendBuff[100] = "hello";
sendto(socketSrv,sendBuff,strlen(sendBuff)+1,0,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));
closesocket(socketSrv);
WSACleanup();
}