一.TCP流式套接字的编程步骤
在使用之前须链接库函数:工程->设置->Link->输入ws2_32.lib,OK!
服务器端程序:
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() { WORD wVersionRequested;//版本号 WSADATA wsaData; int err; wVersionRequested = MAKEWORD( 1, 1 );//1.1版本的套接字 err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) { return; }//加载套接字库,加载失败则返回 if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 ) { WSACleanup( ); return; }//如果不是1.1的则退出 SOCKET sockSrv=socket(AF_INET,SOCK_STREAM,0); //创建套接字(socket)。 SOCKADDR_IN addrSrv; addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY); //转换Unsigned short为网络字节序的格式 addrSrv.sin_family=AF_INET; addrSrv.sin_port=htons(6000); bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR)); //将套接字绑定到一个本地地址和端口上(bind) listen(sockSrv,5);//将套接字设为监听模式,准备接收客户请求(listen)。 SOCKADDR_IN addrClient;//定义地址族 int len=sizeof(SOCKADDR);//初始化这个参数,这个参数必须被初始化 while(1) { SOCKET sockConn=accept(sockSrv,(SOCKADDR*)&addrClient,&len);accept的第三个参数一定要有初始值。 //等待客户请求到来;当请求到来后,接受连接请求,返回一个新的对应于此次连接的套接字(accept)。 //此时程序在此发生阻塞 char sendBuf[100]; sprintf(sendBuf,"Welcome %s to http://www.sunxin.org", inet_ntoa(addrClient.sin_addr)); //用返回的套接字和客户端进行通信(send/recv)。 send(sockConn,sendBuf,strlen(sendBuf)+1,0); char recvBuf[100]; recv(sockConn,recvBuf,100,0); printf("%s\n",recvBuf); closesocket(sockConn);//关闭套接字。等待另一个用户请求 } }
客户端代码如下:
#include <Winsock2.h> #include <stdio.h>void main() { WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD( 1, 1 ); err = WSAStartup( wVersionRequested, &wsaData );加载套接字库 if ( err != 0 ) { return; } if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 ) { WSACleanup( ); return; } SOCKET sockClient=socket(AF_INET,SOCK_STREAM,0);创建套接字(socket)。 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(sockClient,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));向服务器发出连接请求(connect)。 char recvBuf[100];和服务器端进行通信(send/recv)。 recv(sockClient,recvBuf,100,0); printf("%s\n",recvBuf); send(sockClient,"This is lisi",strlen("This is lisi")+1,0); closesocket(sockClient);关闭套接字。 WSACleanup();//必须调用这个函数清除参数 }
二.UDP型套接字。
服务器端(接收端)程序:
1、创建套接字(socket)。
2、将套接字绑定到一个本地地址和端口上(bind)。
3、等待接收数据(recvfrom)。
4、关闭套接字。
客户端(发送端)程序:
1、创建套接字(socket)。
2、向服务器发送数据(sendto)。
3、关闭套接字。
服务器端代码:
#include <Winsock2.h> #include <stdio.h>void main() { WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD( 1, 1 ); err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) { return; } if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 ) { WSACleanup( ); return; } SOCKET sockSrv=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(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR)); SOCKADDR_IN addrClient; int len=sizeof(SOCKADDR); char recvBuf[100]; recvfrom(sockSrv,recvBuf,100,0,(SOCKADDR*)&addrClient,&len); printf("%s\n",recvBuf); closesocket(sockSrv); WSACleanup(); }
客户端代码:
#include <Winsock2.h> #include <stdio.h>void main() { WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD( 1, 1 ); err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) { return; } if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 ) { WSACleanup( ); return; } SOCKET sockClient=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); sendto(sockClient,"Hello",strlen("Hello")+1,0, (SOCKADDR*)&addrSrv,sizeof(SOCKADDR)); closesocket(sockClient); WSACleanup(); }
UDP的不再加注释了。因为它比TCP的简单多了。
3.基于字符界面的聊天程序,用的是UDP式套接字。代码略。
4.如何添加新的工程?
首先选择中Build工具栏,然后在工程管理器上点击右键,选择增加新的工程即可。
#include<stdio.h> #include<Winsock2.h> void main() { WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD( 1, 1 ); err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) { return; } if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 ) { WSACleanup( ); return; } SOCKET sockserver=socket(AF_INET,SOCK_STREAM,0); SOCKADDR_IN addrserver; addrserver.sin_addr.S_un.S_addr=htonl(INADDR_ANY); addrserver.sin_family=AF_INET; addrserver.sin_port=htons(6000); bind(sockserver,(SOCKADDR*)&addrserver,sizeof(SOCKADDR)); listen(sockserver,5); SOCKADDR_IN addrclient; int len=sizeof(SOCKADDR); while(1) { SOCKET sockConn=accept(sockserver,(SOCKADDR*)&addrclient,&len); char sendBuf[100]; sprintf(sendBuf,"welcome %s to my server",inet_ntoa(addrclient.sin_addr)); send(sockConn,sendBuf,strlen(sendBuf)+1,0); char receiveBuf[100]; recv(sockConn,receiveBuf,100,0); printf("%s\n",receiveBuf); closesocket(sockConn); } }
#include<stdio.h> #include<Winsock2.h> void main() { WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD( 1, 1 ); err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) { return; } if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 ) { WSACleanup( ); return; } SOCKET sockclient=socket(AF_INET,SOCK_STREAM,0); SOCKADDR_IN addrclient; addrclient.sin_addr.S_un.S_addr=inet_addr("127.0.0.1"); addrclient.sin_family=AF_INET; addrclient.sin_port=htons(6000); connect(sockclient,(SOCKADDR*)&addrclient,sizeof(SOCKADDR)); char receiveBuf[100]; recv(sockclient,receiveBuf,100,0); printf("%s\n",receiveBuf); send(sockclient,"hello,my name is zhangsan",strlen("hello,my name is zhangsan")+1,0); closesocket(sockclient); WSACleanup(); }
tcp之练习
#include<iostream> #include<Winsock2.h> #include<string> using namespace std; void main() { WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD( 1, 1 ); err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) { return; } if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1) { WSACleanup( ); return; } SOCKET sockserver=socket(AF_INET,SOCK_STREAM,0); SOCKADDR_IN addrserver; addrserver.sin_addr.S_un.S_addr=htonl(ADDR_ANY);转化为字节序 addrserver.sin_family=AF_INET; addrserver.sin_port=htons(6000);//转化为字节序 bind(sockserver,(SOCKADDR*)&addrserver,sizeof(SOCKADDR)); listen(sockserver,5);//监听队列最多出现5个客户端 SOCKADDR_IN addrclient; int len=sizeof(SOCKADDR); //accept最后一个参数实为[in/out] while(1) { SOCKET sockConn=accept(sockserver,(SOCKADDR*)&addrclient,&len); string str="hello,I am server,i know your ip:"; string ip=inet_ntoa(addrclient.sin_addr);//转化为char*类型 send(sockConn,(str+ip).c_str(),str.length()+ip.size()+1,0); char receiveBuf[100]; recv(sockConn,receiveBuf,100,0); cout<<"receive from the client:"<<receiveBuf<<endl; closesocket(sockConn); } system("pause"); }
#include<iostream> #include<Winsock2.h> using namespace std; void main() { 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); SOCKADDR_IN addrclient; addrclient.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");//设置要连接的主机IP,这里用一台机做试验 addrclient.sin_family=AF_INET; addrclient.sin_port=htons(6000); connect(sockclient,(SOCKADDR*)&addrclient,sizeof(SOCKADDR)); char receiveBuf[100]; recv(sockclient,receiveBuf,100,0); cout<<"receive from the server"<<receiveBuf<<endl; send(sockclient,"hello,I am client",strlen("hello,I am client")+1,0); closesocket(sockclient); WSACleanup(); }
先看服务器,然后再开客户端:
网络编程,别忘了加上动态链接库喔
udp之练习
#include<iostream> #include<Winsock2.h> #pragma comment(lib,"WS2_32.lib") using namespace std; void main() { 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 sockserver=socket(AF_INET,SOCK_DGRAM,0); SOCKADDR_IN addrserver; addrserver.sin_addr.S_un.S_addr=htonl(ADDR_ANY); addrserver.sin_family=AF_INET; addrserver.sin_port=htons(6000); bind(sockserver,(SOCKADDR*)&addrserver,sizeof(SOCKADDR)); SOCKADDR_IN addrcient; int len=sizeof(SOCKADDR); char receiveBuf[100]; recvfrom(sockserver,receiveBuf,100,0,(SOCKADDR*)&addrcient,&len); cout<<"来自客户端的消息:"<<receiveBuf<<endl; sendto(sockserver,"hello123",strlen("hello123")+1,0,(SOCKADDR*)&addrcient,len); closesocket(sockserver); WSACleanup(); }
#include<iostream> #include<string> #include<Winsock2.h> #pragma comment(lib,"ws2_32.lib") using namespace std; void main() { 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_DGRAM,0); SOCKADDR_IN addrserver; int len=sizeof(SOCKADDR); addrserver.sin_addr.S_un.S_addr=inet_addr("127.0.0.1"); addrserver.sin_family=AF_INET; addrserver.sin_port=htons(6000); sendto(sockclient,"hello,i am client",strlen("hello,i am client")+1,0,(SOCKADDR*)&addrserver,len); char receiveBuf[100]; recvfrom(sockclient,receiveBuf,100,0,(SOCKADDR*)&receiveBuf,&len); cout<<"接收来自服务器的消息:"<<receiveBuf<<endl; closesocket(sockclient); WSACleanup(); }
这里的服务器给客户端发送消息的时候,客户端接收的为什么是乱码呢?想想
recvfrom获得SOCKADDR,sendto没有获得SOCKADDR
下面是基于UTD的字符界面聊天程序:
服务端:
#include<Winsock2.h> #include<stdio.h> #pragma comment(lib,"ws2_32.lib") void main() { 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 sockserver=socket(AF_INET,SOCK_DGRAM,0); SOCKADDR_IN addrserver; addrserver.sin_addr.S_un.S_addr=htonl(INADDR_ANY); addrserver.sin_family=AF_INET; addrserver.sin_port=htons(6000); bind(sockserver,(SOCKADDR*)&addrserver,sizeof(SOCKADDR)); SOCKADDR_IN addrclient; int len=sizeof(SOCKADDR); char recvBuf[100]; char sendBuf[100]; char tempBuf[200]; while(1) { recvfrom(sockserver,recvBuf,100,0,(SOCKADDR*)&addrclient,&len); if('q'==recvBuf[0]) { sendto(sockserver,"chat end!",strlen("chat end!")+1,0,(SOCKADDR*)&addrclient,len); break; } sprintf(tempBuf,"%s say %s",inet_ntoa(addrclient.sin_addr),recvBuf); printf("%s\n",tempBuf); printf("input data:\n"); gets(sendBuf); sendto(sockserver,sendBuf,strlen(tempBuf)+1,0,(SOCKADDR*)&addrclient,len); } closesocket(sockserver); WSACleanup(); }
客户端:
#include<Winsock2.h> #include<stdio.h> #pragma comment(lib,"ws2_32.lib") void main() { 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_DGRAM,0); SOCKADDR_IN addrserver; addrserver.sin_addr.S_un.S_addr=inet_addr("127.0.0.1"); addrserver.sin_family=AF_INET; addrserver.sin_port=htons(6000); char recvBuf[100]; char sendBuf[100]; char tempBuf[200]; int len=sizeof(SOCKADDR); while(1) { printf("input data:\n"); gets(sendBuf); sendto(sockclient,sendBuf,strlen(sendBuf)+2,0,(SOCKADDR*)&addrserver,sizeof(SOCKADDR)); recvfrom(sockclient,recvBuf,100,0,(SOCKADDR*)&addrserver,&len); if('q'==recvBuf[0]) { sendto(sockclient,"chat end!",strlen("caht end!")+1,0,(SOCKADDR*)&addrserver,len); } sprintf(tempBuf,"%s say %s",inet_ntoa(addrserver.sin_addr),recvBuf); printf("%s\n",tempBuf); } closesocket(sockclient); WSACleanup(); }
效果如下:
有一点瑕疵,自己可以更改。
现在知道为什么前面的服务器向客户端发送字符会出现乱码了吧