⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dosnetworkprogrammimg.txt

📁 DOS下网络编程介绍 Network program in dos env.
💻 TXT
📖 第 1 页 / 共 2 页
字号:
    int s,            //套接字的句柄;
    int level,        //属性的分类;
    int optname,      //要设置的属性;
    char far *optval, //要设置的属性值;
    int optlen        //属性值参数的长度。
);

比如,允许套接字绑定到已经使用的端口:
DWORD value = 1;
int result = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char far *)(&value), sizeof(value));

更详细的内容请参考本目录MSTCPSDK.rar中的winsock.txt。或者查看MSDN,内容大致相同。
9 错误代码errno
errno是Borland C++编译器定义的一个整数型全局变量,很多函数把执行时发生的错误写到errno变量中,也会把执行中执行后的状态写到errno变量中,经常遇到的有以下这些:

#define EISCONN      118   //socket已经连接上
#define ENOTCONN     119   //socket没有连接上
#define EINPROGRESS  126   //函数正在执行中

第五章 TCP编程模型
和UDP协议有所区别,TCP协议的特点在于:

TCP采用超时重传及机制来保证不丢失数据,当一个TCP发送一个数据包后,它启动一个定时器,等待对端确认收到这个包,如果在指定的时间内没有得到确认,将重发这个包。而接收数据包的时候,它将发送一个确认,如果检测到数据包有错,TCP协议丢弃这个数据包,并且不发送确认,那么对端会因为超时而重新发送这个数据包。

一组有序的数据包,到达对端时可能会有后发的数据先到的情况,TCP协议在包首部保存数据包序号,如果有必要,它将对收到的数据重新排序,并以正确的顺序交给应用层。

1 客户端和服务器端的工作模型


TCP的工作方式用上图的客户端/服务器端模型来描述,通信的发起方称为客户端(Client),通信的等待方称为服务器端(Server)。客户端可以随时使用connect函数连接到服务器端,服务器检测到这个连接后,需要使用accept函数接受这个连接,当物务器接受连接后,一个稳定的连接就建立了,双方可以开始互相通过send和recv函数收发数据了,这时通信的两端并没有任何区别。

DOS系统通常用作客户端,服务端通常用Window系统,所以本文主要写DOS操作系统下的TCP客户端编程。

2 连接到服务端
使用connect函数:
int connect(int s, struct sockaddr far *name, int namelen);  s是套接字的句柄;name是服务端的地址;namelen是name数据结构的长度;函数执行成功返回0,不成功返回SOCKET_ERROR(-1),然后使用errno变量得到具体的出错原因。

struct sockaddr和struct sockaddr_in的内容一样,长度一样,所以使用struct sockaddr_in定义变量name,在调用connect函数的时候强制转换成struct sockaddr。

当套接字工作在非阻塞模式下的时候,不管连接成功与否,connect函数会马上返回并返回SOCKET_ERROR(-1),这时并不意味着连接失败,而是表示函数返回的时候连接尚未成功。这时查询errno变量如果不等于EINPROGRESS(126,表示操作正在进行中),才表示连接失败。

非阻塞模式下的连接:
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(6000);
addr.sin_addr.s_addr = inet_addr(“10.0.0.1”);
connect(s, (struct sockaddr far *)(&addr), sizeof(addr));
delay(100);
if(errno != 118)
    printf(“fail to connect”);

3 发送数据
使用send函数:
int send(int s, char far *pBuf, int len, int flags); s是套接字句柄;pBuf是数据缓冲区;len是要发送的数据长度;flags是发送选项,这个参数一般指定为0。如果发送失败,函数返回SOCKET_ERROR(-1),否则返回成功发送的字节数。

dos_sock为每个socket分配一个发送缓冲区和接受缓冲区,用send函数发送数据时,数据并没有马上在网络上进行传递,而是先放到socket的发送缓冲区中,数据会在合时的时候被发送出去。所以前面的“成功发送”指的是成功放入发送缓冲区而已。

函数在阻塞模式和非阻塞模式下的表现有些不同,下面已send函数发送n字节数据为例说明。

在阻塞模式下,如果发送缓冲区的空闲空间足够大,能容纳n字节的数据,这时函数会将数据全部放入发送缓冲区,然后马上返回;如果缓冲区不够大,函数会一边放入数据一边等待,直到把全部数据放入缓冲区为止。在这两种情况下,返回值都是实际发送的字节数n。这时程序比较简单:
int m = send(s, pBuf, n, 0); //m = n

在非阻塞模式下,如果发送缓冲区的空闲空间也能容纳n字节的数据,这时函数也会将数据全部放入发送缓冲区,然后马上返回,返回值就是实际发送的字节数n。当缓冲区不够大,函数也不会等待,而是把一部分数据放入缓冲区后马上返回,这时返回值是实际发送的字节数m。程序可以这样写。
while(n > 0)
{
  m = send(s, pBuf, n, 0);
  if(m == SOCKET_ERROR)
  {
  	 printf(“send error”);
      break;
  }
  pBuf += m; //移动指针,指向剩余的数据
  n -= m;   //剩余的长度
  delay(10);
}

4 接收数据
使用recv函数:
int recv(int s, char far *pBuf, int len, int flags); s是套接字句柄;pBuf是用来返回数据的缓冲区;len是要接受的数据长度;flags是接收选项,一般也指定为0。如果接收失败,返回SOCKET_ERROR(-1),否则返回实际接收的字节数。

在阻塞模式下,函数等待直到有数据到达为止(接收缓冲区不为空),有多少数据到达就返回多少数据。要接收n字节长度的数据,程序如下:
while(n > 0)
{
  m = recv(s, pBuf, n, 0);
  if(m == SOCKET_ERROR)
  {
  	 printf(“recv error”);
      break;
  }
  pBuf += m; //移动指针,指向剩余的数据
  n -= m;   //剩余的长度
}

在非阻塞模式下,如果接收缓冲区中已经有数据,recv的表现方式和阻塞模式相同,函数会马上返回,并视缓冲区中的数据数量返回1到n之间的数据。如果接收缓冲区空,函数不会等待,而是马上返回SOCKET_ERROR(-1)。

5 TCP服务端的介绍
TCP服务端一般应用在Windows系统下,所以下面描述的函数都来自MSDN,并且可以在VC++6.0中使用。

服务端在创建了socket后需要绑定到本地的一个端口上,等待客户端连接到这个端口。使用bind函数:
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(6000); //本机上的一个端口
addr.sin_addr.s_addr = INADDR_ANY; //表示本机
bind(s, (struct sockaddr far *)(&addr), sizeof(addr));

在绑定之后使用listen函数使TCP套接字进入监听状态:
listen(s, 5); 能够可以同时发现5个客户端连接而不遗漏。然后套接字就处于等待连接进入的状态了。

当有客户端向监听中的套接字发起连接后,必须对监听中的套接字调用accept函数,连接才最后被确认。accept函数将新建一个套接字并返回它的句柄,这个新套接字还是和客户端连接的,程序以后可以使用它来和客户端之间收发数据了。
while(1)
{
  SOCKET newSocket = accept(s, 0, 0);
  if(newSocket != INVALID_SOCKET)
  {
      //创建一个新线程
      AfxBeginThread(newThread, LPVOID(newSocket)); 
  }
}
DWORD WINAPI newThread(LPVOID lParam)
{
	SOCKET hSocket = (SOCKET)lParam; 
  // recv(hSocket, pBuf, len, 0);
  // send(hSocket, pBuf, len, 0);
}


总结
文章详细介绍了在MS-DOS操作系统下开发网络客户端程序,也介绍了Windows中的服务端。具体代码请参考董琐英编写的过电压下位机程序。有了上面这些知识,然后仿照过电压程序将会很容易开发出自己的网络应用。




----------------------------------
杨志朋 2008年4月7日
yzp3646@163.com
yzp3646@sina.com
河北旭辉电气股份有限公司




第13页 / 共15页

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -