网络编程

来源:互联网 发布:为什么淘宝那么卡 编辑:程序博客网 时间:2024/04/29 15:00

1.编写一个基于tcp,也就是面向连接的服务器端的应用程序

TcpSrv.cpp

#include <WINSOCK2.H>

#include <stdio.h>

 

//编写一个基于tcp,也就是面向连接的服务器端的应用程序

void mian()

{

         //我们用套接字编写网络应用程序的时候,首先应该加载套接字库

   WORD wVersionRequested;

         WSADATAwsaData;

         interr;

         wVersionRequested=MAKEWORD(1,1);

         err=WSAStartup(wVersionRequested,&wsaData);

         if(err!=0){

                   return;

         }

         if(LOBYTE(wsaData.wVersion)!=1||

                   HIBYTE(wsaData.wVersion)!=1){

                   WSACleanup();

                   return;

         }

         //创建套接字

         SOCKETsockSrv=socket(AF_INET,SOCK_STREAM,0);

   //接下来就应该将这个套接字绑定到一个本地地址和端口上

   

         SOCKADDR_INaddrSrv;

         //这里使用的是网络字节序

   //htonl它是转换一个u_long类型,从主机字节序到TCP/IP网络字节序

   //这个函数时转换一个u_short类型,从主机字节序到TCP/IP网络字节序

         addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY);

         //地址族

         addrSrv.sin_family=AF_INET;

         //端口,端口号是两个字节的,所以应该用htons来转换

         addrSrv.sin_port=htons(6000);

  

         //绑定到一个本地地址和端口上

         bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));

         //将套接字设置为监听模式,监听我们的连接请求

         listen(sockSrv,5);

 

         //在调用Accep函数时,定义一个地址结构体的变量,用来接收客户端的地址信息

         SOCKADDR_INaddrClient;

         //定义一个整形的变量,赋初始值,这个初始值就是结构体的长度

         intlen=sizeof(SOCKADDR);

 

         //这是一个死循环。因为作为服务器端程序来说,它需要不断的去等待

         //客户端连接请求的到来,所以我们做一个循环,让它能够持续的运行下去

         while(1)

         {

                   //调用accept函数,去等待客户的连接到来并接受客户的连接请求

                   //去定义一个套接字的变量

                   SOCKETsockConn=accept(sockSrv,(SOCKADDR*)&addrClient,&len);

                   //当客户端的连接请求到来的时候,我们接受了这个连接请求

                   //建立了这个连接,同时返回了相对于这个连接的套接字

                   //那么接下来我们就可以进行通信了:

                   //我们可以向客户端发送数据,用send函数

       char sendBuf[100];

                   //将一个数据格式化到buffer当中,将客户端的一个地址做一个

                   //格式化放到sendBuf当中

                   //inet_ntoa这个函数是接收in_addr类型的参数,然后返回一个

                   //点分十进制格式表示的IP地址的一个字符串

                   sprintf(sendBuf,"Welcome%s to http://www.sunxin.org",

                            inet_ntoa(addrClient.sin_addr));

                   //发送,这个套接字应该用建立连接相所对应的套接字,

                   //而不要用处于监听状态的套接字

                   send(sockConn,sendBuf,strlen(sendBuf)+1,0);

                   //定义一个字符数组,用来接收

                   charrecvBuf[100];

                   recv(sockConn,recvBuf,100,0);

                   //将接收到的数据打印出来

                   printf("%s\n",recvBuf);

                   //关闭套接字,释放为套接字所分配的资源

       closesocket(sockConn);

         }

    //接下来需要去链接一个库文件。Project->Setting->Link

         //在Object/librarymodules中的内容移动到最后,然后添加ws2_32.lib

}

 

TcpClient.cpp

#include <WINSOCK2.H>

#include <stdio.h>

void mian()

{

         //我们用套接字编写网络应用程序的时候,首先应该加载套接字库

    WORDwVersionRequested;

         WSADATAwsaData;

         interr;

         wVersionRequested=MAKEWORD(1,1);

         err=WSAStartup(wVersionRequested,&wsaData);

         if(err!=0){

                   return;

         }

         if(LOBYTE(wsaData.wVersion)!=1||

                   HIBYTE(wsaData.wVersion)!=1){

                   WSACleanup();

                   return;

         }

         SOCKETsockClient=socket(AF_INET,SOCK_STREAM,0);

         //定义一个地址结构体的变量

         SOCKADDR_INaddrSrv;

         //然后对它的成员进行赋值,这里我们要设定服务器端它的IP地址

         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));

 

         charrecvBuf[100];

         recv(sockClient,recvBuf,100,0);

         printf("%s\n",recvBuf);

         send(sockClient,"Thisis zhangsan",strlen("This is zhangsan")+1,0);

 

         closesocket(sockClient);

         WSACleanup();

}

 

2.基于UDP的,也就是面向无连接的,网络应用程序的编写:

在UdpSrv.cpp中:

#include <WINSOCK2.H>

#include <stdio.h>

void mian()

{

   WORD wVersionRequested;

         WSADATAwsaData;

         interr;

         wVersionRequested=MAKEWORD(1,1);

         err=WSAStartup(wVersionRequested,&wsaData);

         if(err!=0){

                   return;

         }

         if(LOBYTE(wsaData.wVersion)!=1||

                   HIBYTE(wsaData.wVersion)!=1){

                   WSACleanup();

                   return;

         }

 

         //创建一个套接字,因为是基于UDP的,所以创建的是数据报套接字;

         SOCKETsockSrv=socket(AF_INET,SOCK_DGRAM,0);

   //用SOCKADDR_IN这个结构体定义一个变量;

         SOCKADDR_INaddrSrv;

         //然后对结构体的数据成员进行赋值;

         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_INaddrClient;

         //然后定义一个变量,并给它赋一个初始值

         intlen=sizeof(SOCKADDR);

         //定义一个字符数组,用来接收数据;

         charrecvBuf[100];

 

         recvfrom(sockSrv,recvBuf,100,0,(SOCKADDR*)&addrClient,&len);

         printf("%s\n",recvBuf);

         closesocket(sockSrv);

         WSACleanup();

}

 

在UdpClient.cpp中:

#include <WINSOCK2.H>

#include <stdio.h>

void mian()

{

         //我们用套接字编写网络应用程序的时候,首先应该加载套接字库

   WORD wVersionRequested;

         WSADATAwsaData;

         interr;

         wVersionRequested=MAKEWORD(1,1);

         err=WSAStartup(wVersionRequested,&wsaData);

         if(err!=0){

                   return;

         }

         if(LOBYTE(wsaData.wVersion)!=1||

                   HIBYTE(wsaData.wVersion)!=1){

                   WSACleanup();

                   return;

         }

         SOCKETsockClient=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();

}

小总结:对于一个面向无连接的套接字编程来说非常简单,因为它不需要去建立连接。所有对客户端来说,在创建完套接字之后就可以直接用sendto去发送数据了。我们要注意的是基于TDP的和基于UDP的它们在使用接收数据和发送数据的时候调用的函数是不一样的,前者是用send和recv,后者是用的sendto和recvfrom这两个函数。

 

3.编写一个基于字符界面的聊天程序:

对于聊天类的软件我们通常会用基于UDP的方式来实现,因为UDP不需要建立连接而且没有数据确认和数据重传的机制,所以实施性较高,在聊天时即使丢失一些数据也不会影响信息的交流,我们可以根据上下文的语义推测出对方要表达的意思。

而在聊天中TCP面向连接,数据确认与重传的机制,将会影响聊天的效率。

 

在NetSrv.cpp中:

#include <WINSOCK2.H>

#include <stdio.h>

 

void mian()

{

         //我们用套接字编写网络应用程序的时候,首先应该加载套接字库

   WORD wVersionRequested;

         WSADATAwsaData;

         interr;

         wVersionRequested=MAKEWORD(1,1);

         err=WSAStartup(wVersionRequested,&wsaData);

         if(err!=0){

                   return;

         }

         if(LOBYTE(wsaData.wVersion)!=1||

                   HIBYTE(wsaData.wVersion)!=1){

                   WSACleanup();

                   return;

         }

         //创建套接字

         SOCKETsockSrv=socket(AF_INET,SOCK_DGRAM,0);

   //对于服务器端,也就是我们这里的接收端首先需要绑定

   //先定义一个地址结构体的变量

   SOCKADDR_IN addrSrv;

         //然后对地址结构体中的成员进行赋值

   addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY);

   addrSrv.sin_port=htons(6000);

 

         //将套接字和本地主机的地址和端口进行绑定

         bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));

 

         //定义字符数组接收信息和发送信息和存放中间数据;

         charrecvBuf[100];

         charsendBuf[100];

   char tempBuf[200];

 

   //我们接收的时候需要获取和我们通信的这一方的地址信息

   //先定义一个地址结构体的变量;

         SOCKADDR_INaddrClient;

         //定义一个长度,初始化的值是地址结构体的长度

         intlen=sizeof(SOCKADDR);

 

         //做一个while循环,保证我们通信的过程可以不断的继续下去;

         while(1)

         {

                   //接收数据

                   recvfrom(sockSrv,recvBuf,100,0,(SOCKADDR*)&addrClient,&len);

       //当我们收到数据的时候,做一个判断,判断这个数据的第一个字符

                   //是不是‘q’,如果是‘q’表面跟我们通讯的这一方它想退出,既然

                   //它想退出,那么我们给对方也发送一个字符‘q’

                   if('q'==recvBuf[0])

                   {

                            sendto(sockSrv,"q",strlen("q")+1,0,(SOCKADDR*)&addrClient,len);

                            printf("Charend!\n");

                       break;

                   }

                   //如果不是‘q’说明我们收到了客户发过来的数据,我们可以将这个

                   //数据做一个格式化,然后放到tempBuf当中

                   //将对方的IP地址取出来

                   sprintf(tempBuf,"%ssay : %s",inet_ntoa(addrClient.sin_addr),recvBuf);

                   //将数据打印输出

                   printf("%s\n",tempBuf);

                  

                   //我们应该根据它的输出来回复一个信息,这个回复信息,我们希望通过

                   //标准的输入设备来获取,也就是说从用户的键盘输入,可以调用gets()函数

       //可以从标准输入流当中获取一行数据,当我们通过键盘输入一行数据之后

                   //一回车,这个数据就放到了指定的字符指针所指向的内存buffer当中

       //接下来我们可以将输入发送到客户端。

                   printf("pleaseinput data:\n");

                   gets(sendBuf);

                   sendto(sockSrv,sendBuf,strlen(sendBuf)+1,0,(SOCKADDR*)&addrClient,len);

         }

         closesocket(sockSrv);

         WSACleanup();

}

 

在NetClient.cpp中:

#include <WINSOCK2.H>

#include <stdio.h>

 

void mian()

{

         //我们用套接字编写网络应用程序的时候,首先应该加载套接字库

   WORD wVersionRequested;

         WSADATAwsaData;

         interr;

         wVersionRequested=MAKEWORD(1,1);

         err=WSAStartup(wVersionRequested,&wsaData);

         if(err!=0){

                   return;

         }

         if(LOBYTE(wsaData.wVersion)!=1||

                   HIBYTE(wsaData.wVersion)!=1){

                   WSACleanup();

                   return;

         }

         SOCKETsockClient=socket(AF_INET,SOCK_DGRAM,0);

   //对于基于UDP的客户端来说,也就是发送端,它不需要去绑定

   //但是,它需要去设定你要发送到对方的机器的地址信息

         SOCKADDR_INaddrSrv;

         addrSrv.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");

         addrSrv.sin_family=AF_INET;

         addrSrv.sin_port=htons(6000);

 

         charrecvBuf[100];

         charsendBuf[100];

         chartempBuf[200];

 

         //要定义一个变量,在我们接收一个数据的时候要返回地址结构的长度

         //我们用这个变量去接收所返回的地址结构的长度,这个变量必须经过初始化

         intlen=sizeof(SOCKADDR);

 

         while(1)

         {

                   printf("pleaseinput data:\n");

                   //这是要发送的数据

                   gets(sendBuf);

                   //得到数据之后,就要发送了

                   sendto(sockClient,sendBuf,strlen(sendBuf)+1,0,

                            (SOCKADDR*)&addrSrv,len);

                   //发送数据之后,我们就要等待服务器端对我们的回应信息

                   recvfrom(sockClient,recvBuf,100,0,(SOCKADDR*)&addrSrv,&len);

        if('q'==recvBuf[0])

                   {

                            sendto(sockClient,"q",strlen("q")+1,0,

                                     (SOCKADDR*)&addrSrv,len);

                            printf("Charend!\n");

                            break;

                   }

                   sprintf(tempBuf,"%ssay: %s",inet_ntoa(addrSrv.sin_addr),recvBuf);

       printf("%s\n",tempBuf);

         }

         //关闭套接字

   closesocket(sockClient);

         //终止对套接字库的使用

   WSACleanup();

}

 

原创粉丝点击