WSAStartup()函数、socket、SOCKADDR_IN对象及accept等在一个类似飞鸽传书软件中的应用,最近参加公司的ERP,真忙,由于时间因素等,所以只大概的写了个局域网TCP/IP传送文件的程序。
服务器端:
一、加载套接字库
1、WSAStartup函数加载套接字库,因为我们以后想要用到的一些网络函数,就必须加载它,还有就是确定
TCP/IP版本。
二、利用socket可以创建套接字SOCKET socketClient=socket(AF_INET,SOCK_STREAM,0)。
三、SOCKADDR_IN对象,用来存储服务器基本信息,如端口等。然后可以用bind将套接字和SOCKADDR_IN对象绑定,
利用listen函数确定同时能连接服务器客服端的个数。
四、利用accept接受客服端与服务器的连接并产生连接套接字。
五、然后利用recv接受客服端发送给服务器的信息。
六、文件传送实现
1、当接收到信息时我对接受到的二进制的第一个字节进行判断。如果为'1'说明后面的数据是文件名,'0'说明是文件内容,'2'说明文件快要到结束了,并且最后的字节个数(然后下一条收到的就是文件最后的几个数 据)。'3'普通字符数据。
2、我用的是fwrite些文件,不过一定要记得用二进制方式打开该文件,否则文件会读取出错。fopen(fileName,"wb")。
客户端:
一、客服端与服务器的写法差不多只不过SOCKADDR_IN 中参数.sin_addr.S_un.S_addr=inet_addr(主机IP地址)变一下。
二、利用connect去连接主机
三、将发首先将文件名发送过去,然后再从文件中读取一定字节的二进制信息,加上特定信息符(0,1,2,3)然后发送。
未解决的问题:
如果客服端不设置延时的发送数据,会出现“粘包”现象,从而服务器会出现丢包和卡死的现象。
如果设置延时速度又会很慢。如果就单纯聊天用,则不会出现该情况。
至于如何得知局域网登录了该程序,我的想法是的去自己本机的IP地址(gethostname,gethostbyname)然后在向所有该网段主机发送连接,如果连接上则记录IP地址,然后断开连接,以后要用在连。
WSAStartup()函数说明:
int WSAStartup(WORD wVersionRequested,LPWSADATA lpWSAData);
注明:对于参数WORD wVersionRequested主要是对socket库版本的申请,通过MAKEWORD( int x, int y);设置所申请的套接字的版本号即可。对于参数LPWSADATA lpWSAData是一个WSDATA 类型的指针,其目的是接受系统分配的真正的套接字库的版本的信息,其实是借助WSDATA结构体里的一个属性WORD wVersion; 来定义WSDATA WS变量,其中LOBYTE(WS.wVersion)对应于主版本而HIBYTE(WS.wVersion)对应于副版本,那么就可以与MAKEWORD函数设置的版本号进行相比较了,主要目的就是检测申请的版本号和系统分配的版本号是否一致。
实质就是如果一个应用程序调用WSAStartup函数,那么操作系统会按照请求的socket版本来进行寻找对应的socket库,把所找到的socket库加载进来,如果以后需要对应用程序进行撰写时,就可以轻松的调用所请求的socket库中的socket函数了,该函数若执行成功则会返回0。
附带代码清单:
WORD request; WSADATA ws; request = MAKEWORD(1,1); int err = WSAStartup(request,&ws); if(err != 0) { return ; } if(LOBYTE(ws.wVersion) != 1||HIBYTE(ws.wVersion) != 1) { WSACleanup(); return ; } |
注明:WSAStartup函数主要是初始化Winsock DLL,而WSACleanup()函数主要是为了解除Socket库的加载并且释放一定的资源。所以WSAStartup()函数和WSACleanup()函数是成对使用的。
相关阅读:wsastartup的使用