C#.NET通过Socket实现平行主机之间网络通讯

C#.NET通过Socket实现平行主机之间网络通讯,第1张

在程序设计中 涉及数据存储和数据交换的时候 不管是B/S还是C/S模式 都有这样一个概念 这要求一台性能和配置都比较好的主机作为服务器 以满足数目众多的客户端进行频繁访问 但是对于一些数据交换的要求不主同 而且涉及到的通讯个体数目不多 如果还采用 一主机多客户机 的模式 便要求一台配置良好而且上安装了相关数据服务软件 这样会造成硬件和软件上的很多不必要的成本 这时Socket在点对点的平行对象之间的通讯的优势就就发挥出来了

其实对于Socket通讯来说 服务器和客户端的界定不像数据库服务器与客户端那样明显 甚至可以说Socket通讯里面的服务器和客户端只是相对的 因为网络通讯的对象基本上是处于平等层面的 只是为了方便对两台联网通讯的主机的描述才这样定义称谓的

由于在中Socket通讯的建立很容易 所以本文主要介绍一个Socket的比较典型的应用的流程 客户端向服务器发送请求 服务器接收到请求 并将服务器上的编码 发送到客户端 客户端得到数据后 再将这些数据写成文件 保存在客户端上

本文主要是对Socket的一个应用进行介绍 所以至于其原理在此没有深究 至于如何建立Socket还有如何实现网络的七层协议在此都没有进行相关研究和介绍 本文主要介绍如何实现一个用户想要的功能 即在两台主机之间进行通讯 通过网络来收发用户想要收发的数据

一 通讯流程图

[nextpage]  

三 测试socket的连接方法 telnet远程登录

用户可以同时对客户端和端的Socket程序进行编写 然后进行联调 也可以一次只编写一个 然后通过下面的方法来测试Socket连接

一般通过远程登录来测试连接是否成功 比如测试本机的 端口是否能连接成功

运行->cmd->telnet

在没有运行对本机的 端口进行不断侦听的程序时 会出现连接失败的提示

如果连接成功 则会d出另外一个窗口

如果在侦听线程里面设置断点 通常连接成功后 就会在

Socket sRecmdTemp = sRecvCmd Accept();

之后的语句上断点

附近演示程序的说明

使用VS 创建

主要实现的功能是 主机A向主机B发请求 主机B将D盘image目录下的image jpg image jpg文件编码发送到主机B 主机B再解码并写成文件到E盘的image目录下

为了方便调试 演示程序将服务器和客户端同时放在本机上 即localhost或者 即本程序最终实现的效果就是将本机的D 盘image目录下的两个指定名称的传送到E盘image目录下 所以在运行本程序前 先在D:/image目录下放置两张命名为 image jpg image jpg的文件

lishixinzhi/Article/program/net/201311/11802

1PC服务器启用ServerSocket两个通信实体在建立虚拟链路之前,需要有一方先准备好,主动接受来自其他通信实体的连接请求。使用ServerSocket对象监听来自客户端的Socket连接。//创建ServerSocket对象ServerSocketss=newServerSocket(30000);//监听来自客户端的请求while(true){Sockets=ssaccept();…}如果没有连接,则将一直处于等待状态。当接收到连接请求后,获取消息到输入流,并保存到文件。//接收客户端消息BufferedReaderin=newBufferedReader(newInputStreamReader(clientgetInputStream()));Stringstr;BufferedWriterbw=newBufferedWriter(newFileWriter("D:/ApInfo"+(i++)+"txt"));while((str=inreadLine())!=null){Systemoutprintln(str);bwwrite(str);bwnewLine();}2Android终端使用Socket通信客户端使用Socket的构造器连接服务器,指定服务器IP和端口号就可以了。Sockets=newSocket(“1921681100”,30000);这样服务器端的accept()方法就得到响应,从而向下执行,服务器端和客户端就形成了一对互相连接的Socket。再进行通信时就没有服务器和客户端之分了,都是通过输入输出流进行通信。详细步骤:采用Handler和TimerTask来定时扫描AP信息并发送给服务器端。TimerTask规定了到达指定的时间所要进行的任务。TimerTasktask=newTimerTask(){publicvoidrun(){Messagemessage=newMessage();messagewhat=1;handlersendMessage(message);}};handler传递message内容:Handlerhandler=newHandler(){publicvoidhandleMessage(Messagemsg){switch(msgwhat){case1://执行定时器时间到了之后由handler传递的任务break;}superhandleMessage(msg);}}接下来扫描AP信息并发送给服务器端,然后将结果保存。WifiManagerwifiManager=(WifiManager)getSystemService(WIFI_SERVICE);wifiManagerstartScan();mWifiList=wifiManagergetScanResults();由WifiManager说明可知,它可以用于处理已配置的网络,当前连接的网络及AP信息的扫描等情况。向服务器发送消息:socket=newSocket("1921681211",30000);//向服务器端发送消息PrintWriterout=newPrintWriter(newBufferedWriter(newOutputStreamWriter(socketgetOutputStream())),true);outprintln(message);其中message为获取的AP信息,测试收到的信息格式为:SSID:ICIS_LAB,BSSID:1c:af:f7:9a:65:e4,capabilities:[WPA-PSK-TKIP+CCMP],level:-80,frequency:2437

这是在网上找到的,希望对你有所帮助。
sockets(套接字)编程有三种,流式套接字(SOCK_STREAM),数据报套接字(SOCK_DGRAM),原始套接字(SOCK_RAW);
WINDOWS环境下TCP/UDP编程步骤:
1 基于TCP的socket编程是采用的流式套接字。
在这个程序中,将两个工程添加到一个工作区。要链接一个ws2_32lib的库文件。
服务器端编程的步骤:
1:加载套接字库,创建套接字(WSAStartup()/socket());
2:绑定套接字到一个IP地址和一个端口上(bind());
3:将套接字设置为监听模式等待连接请求(listen());
4:请求到来后,接受连接请求,返回一个新的对应于此次连接的套接字(accept());
5:用返回的套接字和客户端进行通信(send()/recv());
6:返回,等待另一连接请求;
7:关闭套接字,关闭加载的套接字库(closesocket()/WSACleanup())。
服务器端代码如下:
#include <stdioh>
#include <Winsock2h>
void main()
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 1, 1 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 ) {
return;
}
if ( LOBYTE( wsaDatawVersion ) != 1 ||
HIBYTE( wsaDatawVersion ) != 1 ) {
WSACleanup( );
return;
}
SOCKET sockSrv=socket(AF_INET,SOCK_STREAM,0);
SOCKADDR_IN addrSrv;
addrSrvsin_addrS_unS_addr=htonl(INADDR_ANY);
addrSrvsin_family=AF_INET;
addrSrvsin_port=htons(6000);
bind(sockSrv,(SOCKADDR)&addrSrv,sizeof(SOCKADDR));
listen(sockSrv,5);
SOCKADDR_IN addrClient;
int len=sizeof(SOCKADDR);
while(1)
{
SOCKET sockConn=accept(sockSrv,(SOCKADDR)&addrClient,&len);
char sendBuf[50];
sprintf(sendBuf,"Welcome %s to here!",inet_ntoa(addrClientsin_addr));
send(sockConn,sendBuf,strlen(sendBuf)+1,0);
char recvBuf[50];
recv(sockConn,recvBuf,50,0);
printf("%s\n",recvBuf);
closesocket(sockConn);
}
}
客户端编程的步骤:
1:加载套接字库,创建套接字(WSAStartup()/socket());
2:向服务器发出连接请求(connect());
3:和服务器端进行通信(send()/recv());
4:关闭套接字,关闭加载的套接字库(closesocket()/WSACleanup())。
客户端的代码如下:
#include <stdioh>
#include <Winsock2h>
void main()
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 1, 1 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 ) {
return;
}
if ( LOBYTE( wsaDatawVersion ) != 1 ||
HIBYTE( wsaDatawVersion ) != 1 ) {
WSACleanup( );
return;
}
SOCKET sockClient=socket(AF_INET,SOCK_STREAM,0);
SOCKADDR_IN addrSrv;
addrSrvsin_addrS_unS_addr=inet_addr("127001");
addrSrvsin_family=AF_INET;
addrSrvsin_port=htons(6000);
connect(sockClient,(SOCKADDR)&addrSrv,sizeof(SOCKADDR));
char recvBuf[50];
recv(sockClient,recvBuf,50,0);
printf("%s\n",recvBuf);
send(sockClient,"hello",strlen("hello")+1,0);
closesocket(sockClient);
WSACleanup();
}
2基于UDP的socket编程是采用的数据报套接字。
在这个程序中,将两个工程添加到一个工作区。同时还要链接一个ws2_32lib的库文件。
服务器端编程的步骤:
1:加载套接字库,创建套接字(WSAStartup()/socket());
2:绑定套接字到一个IP地址和一个端口上(bind());
3:等待和接收数据(sendto()/recvfrom());
4:关闭套接字,关闭加载的套接字库(closesocket()/WSACleanup())。
服务器端代码如下:
#include <winsock2h>
#include <stdioh>
void main()
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 1, 1 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 )
{
return;
}
if ( LOBYTE( wsaDatawVersion ) != 1 ||
HIBYTE( wsaDatawVersion ) != 1 )
{
WSACleanup( );
return;
}
SOCKET sockSrv=socket(AF_INET,SOCK_DGRAM,0);
SOCKADDR_IN addrSrv;
addrSrvsin_addrS_unS_addr=htonl(INADDR_ANY);
addrSrvsin_family=AF_INET;
addrSrvsin_port=htons(7003);
bind(sockSrv,(SOCKADDR)&addrSrv,sizeof(SOCKADDR));
char recvBuf[50];
SOCKADDR addrClient;
int len=sizeof(SOCKADDR);
recvfrom(sockSrv,recvBuf,50,0,(SOCKADDR)&addrClient,&len);
printf("%s\n",recvBuf);
closesocket(sockSrv);
WSACleanup();
}
对于基于UDP的socket客户端来说,要进行如下步骤:
1:创建一个套接字(socket);
2:向服务器发送数据(sendto);
3:关闭套接字;
代码如下:
#include <winsock2h>
#include <stdioh>
void main()
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 2, 2 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 ) {
return;
}
if ( LOBYTE( wsaDatawVersion ) != 2 ||
HIBYTE( wsaDatawVersion ) != 2 ) {
WSACleanup( );
return;
}
SOCKET sockClient=socket(AF_INET,SOCK_DGRAM,0);
SOCKADDR_IN addrClient;
addrClientsin_addrS_unS_addr=inet_addr("127001");
addrClientsin_family=AF_INET;
addrClientsin_port=htons(8889);
SOCKADDR_IN addrSrv;
sendto(sockClient,"hi",3,0,(SOCKADDR)&addrClient,sizeof(SOCKADDR));
}
LINUX环境下TCP/UDP编程步骤:
TCP编程步骤:
一 服务端:
1socket(int domain,int type,int protocol):建立套接字;
2 bind(int sockid,struct sockaddr addrp,socklen_t addrlen):把本机地址和端口跟上一步建立的socket绑定在一起;
3listen(int sockid,int qsize):监听某套接字;
4fd=accept(int sockid,struct sockaddr callerid,socklen_t addrlenp):等待某套接字接收信息;
5recv(int fd,void buf,size_t nbytes,int flags):从套接字接收数据;
6close(fd) 和close(sockid)
二客户端:
1 socket():建立套接字;
2connect(int sockid,struct sockaddr serv_addrp,socklen_t addrlen):连接到服务器;
3 send(int sockfd,const void buf,size_t nbytes,int flags):发送数据到服务器
4 close(sockid);
UDP编程步骤:
一,服务端:
1 socket():同上;
2 bind():同上;
3 recvfrom(int sockfd,voidbuff,size_t nbytes,int flags,struct sockaddrfrom,socklen_taddrlen):在套接字口接收数据,并且记录下接收到的数据来源;一定要注意这里的参数addrlen,它不仅是函数的输出,也是函数的输入!所以要在调用该函数之前对addrlen赋值sizeof(struct sockaddr)。否则返回的地址from将会出错!
4 close(sockfd);
二 客户端:
1 socket();同上;
2 sendto(int sockfd,const voidbuff,size_t nbytes,int flags,const struct sockaddrto,socklen_t addrlen):往指定的地址发送数据;
3 close(sockfd);

获取从客户端读入的字符串
String result = bufferedReaderreadLine(); 这里会阻塞。
你服务器端获取Socket以后 需要另外启动一个线程去处理,你现在是单线程的服务器端设计,当然只能接收一次请求了。
服务器端接收到Socket以后应该启动一个线程
new Thread(new Runable(){

})start();

你可以在每个用户连上服务器端时,都发送一个消息,就是用4个字节表示是用户的ID,并将与用户通信的socket,用一个HashMap存储起来,而不是用LinkList。
后面如果A发送消息给C,就把A的前四个字节(即ID)取出来,在HashMap中找到与C通信的socket,然后把消息通过socket发送出去····
这部分代码应该很容易实现的,Socket通信这东西,理清了思路就很好弄了~~

netty提供了客户端和服务端之间基于socket的服务调用。用于可以定制自己的协议和规范。dubbo框架底层正是使用netty进行相关的数据传输。

下面我们实现客户端像服务器端发送请求,服务器端接受消息后向客户端进行响应。

服务器端自定义handler

客户端自定义handler

分别启动服务器端和客户端,观察控制台输出:


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zz/10597597.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-09
下一篇 2023-05-09

发表评论

登录后才能评论

评论列表(0条)

保存