Socket客户端和服务端的编程实现C和android附运行截图文档格式.docx
《Socket客户端和服务端的编程实现C和android附运行截图文档格式.docx》由会员分享,可在线阅读,更多相关《Socket客户端和服务端的编程实现C和android附运行截图文档格式.docx(20页珍藏版)》请在冰豆网上搜索。
![Socket客户端和服务端的编程实现C和android附运行截图文档格式.docx](https://file1.bdocx.com/fileroot1/2022-11/26/3c569cce-587c-4750-a1d5-be5a143a8ab0/3c569cce-587c-4750-a1d5-be5a143a8ab01.gif)
Socket正如其英文原意那样,像一个多孔插座。
一台主机犹如布满各种插座的房间,每个插座有一个编号,有的插座提供220伏交流电,有的提供110伏交流电,有的则提供有线电视节目。
客户软件将插头插到不同编号的插座,就可以得到不同的服务。
常用的Socket类型有两种:
流式Socket(SOCK_STREAM)和数据报式Socket(SOCK_DGRAM)。
流式是一种面向连接的Socket,针对于面向连接的TCP服务应用;
数据报式Socket是一种无连接的Socket,对应于无连接的UDP服务应用。
Socket建立为了建立Socket,程序可以调用Socket函数,该函数返回一个类似于文件描述符的句柄。
socket函数原型为:
intsocket(intdomain,inttype,intprotocol);
domain指明所使用的协议族,通常为PF_INET,表示互联网协议族(TCP/IP协议族);
type参数指定socket的类型:
SOCK_STREAM或SOCK_DGRAM,Socket接口还定义了原始Socket(SOCK_RAW),允许程序使用低层协议;
protocol通常赋值"
0"
。
Socket()调用返回一个整型socket描述符,你可以在后面的调用使用它。
Socket描述符是一个指向内部数据结构的指针,它指向描述符表入口。
调用Socket函数时,socket执行体将建立一个Socket,实际上"
建立一个Socket"
意味着为一个Socket数据结构分配存储空间。
Socket执行体为你管理描述符表。
两个网络程序之间的一个网络连接包括五种信息:
通信协议、本地协议地址、本地主机端口、远端主机地址和远端协议端口。
Socket数据结构中包含这五种信息。
Socket在测量软件中的使用也很广泛。
2.实验步骤
本实验在VisualStudio2010以及安卓模拟器下实现,项目包括安卓客户端源码和服务端C#源码,本机ip为127.0.0.1,实验要实现客户端与服务端在4567号端口的通信,具体代码如下:
服务端核心代码:
usingSystem;
usingSystem.Collections.Generic;
usingSystem.ComponentModel;
usingSystem.Data;
usingSystem.Drawing;
usingSystem.Linq;
usingSystem.Text;
usingSystem.Windows.Forms;
usingSystem.Collections;
usingSystem.Net;
usingSystem.Net.Sockets;
usingSystem.Threading;
namespaceMySocketServer
{
publicpartialclassFormServer:
Form
{
publicFormServer()
InitializeComponent();
}
//保存与客户相关的信息列表
ArrayListfriends=newArrayList();
//负责监听的套接字
TcpListenerlistener;
//只是是否启动了监听
boolIsStart=false;
//对控件进行调用委托类型和委托方法
//在列表中写字符串
delegatevoidAppendDelegate(stringstr);
AppendDelegateAppendString;
//在建立列表时,向下拉列表中添加客户信息
delegatevoidAddDelegate(MyFriendfrd);
AddDelegateAddfriend;
//在断开连接时,从下拉列表中删除客户信息
delegatevoidRemoveDelegate(MyFriendfrd);
RemoveDelegateRemovefriend;
//在列表中写字符串的委托方法
privatevoidAppendMethod(stringstr)
listBoxStatu.Items.Add(str);
listBoxStatu.SelectedIndex=listBoxStatu.Items.Count-1;
listBoxStatu.ClearSelected();
//向下拉列表中添加信息的委托方法
privatevoidAddMethod(MyFriendfrd)
lock(friends)
friends.Add(frd);
comboBoxClient.Items.Add(frd.socket.RemoteEndPoint.ToString());
//从下拉列表中删除信息的委托方法
privatevoidRemoveMethod(MyFriendfrd)
inti=friends.IndexOf(frd);
comboBoxClient.Items.RemoveAt(i);
friends.Remove(frd);
frd.Dispose();
privatevoidFormServer_Load(objectsender,EventArgse)
//实例化委托对象,与委托方法关联
AppendString=newAppendDelegate(AppendMethod);
Addfriend=newAddDelegate(AddMethod);
Removefriend=newRemoveDelegate(RemoveMethod);
//获取本机IPv4地址
List<
string>
listIP=getIP();
if(listIP.Count==0)
boBoxIP.Items.Clear();
boBoxIP.Text="
未能获取IP!
"
;
elseif(listIP.Count==1)
boBoxIP.Items.Add(listIP[0]);
boBoxIP.SelectedIndex=0;
else
foreach(stringstrinlistIP)
boBoxIP.Items.Add(str);
请选择IP!
//设置默认端口号
textBoxServerPort.Text="
4567"
privatevoidbuttonStart_Click(objectsender,EventArgse)
//服务器已在其中监听,则返回
if(IsStart)
return;
//服务器启动侦听
IPEndPointlocalep=newIPEndPoint(IPAddress.Parse(comboBoxIP.Text),int.Parse(textBoxServerPort.Text));
listener=newTcpListener(localep);
listener.Start(10);
IsStart=true;
listBoxStatu.Invoke(AppendString,string.Format("
服务器已经启动监听!
端点为:
{0}。
listener.LocalEndpoint.ToString()));
//接受连接请求的异步调用
AsyncCallbackcallback=newAsyncCallback(AcceptCallBack);
listener.BeginAcceptSocket(callback,listener);
this.buttonStart.Enabled=false;
privatevoidAcceptCallBack(IAsyncResultar)
try
//完成异步接收连接请求的异步调用
//将连接信息添加到列表和下拉列表中
Sockethandle=listener.EndAcceptSocket(ar);
MyFriendfrd=newMyFriend(handle);
comboBoxClient.Invoke(Addfriend,frd);
AsyncCallbackcallback;
//继续调用异步方法接收连接请求
callback=newAsyncCallback(AcceptCallBack);
//开始在连接上进行异步的数据接收
frd.ClearBuffer();
callback=newAsyncCallback(ReceiveCallback);
frd.socket.BeginReceive(frd.Rcvbuffer,0,frd.Rcvbuffer.Length,SocketFlags.None,callback,frd);
catch
//在调用EndAcceptSocket方法时可能引发异常
//套接字Listener被关闭,则设置为未启动侦听状态
IsStart=false;
privatevoidReceiveCallback(IAsyncResultar)
MyFriendfrd=(MyFriend)ar.AsyncState;
inti=frd.socket.EndReceive(ar);
if(i==0)
comboBoxClient.Invoke(Removefriend,frd);
stringdata=Encoding.UTF8.GetString(frd.Rcvbuffer,0,i);
data=string.Format("
From[{0}]:
{1}"
frd.socket.RemoteEndPoint.ToString(),data);
listBoxStatu.Invoke(AppendString,data);
AsyncCallbackcallback=newAsyncCallback(ReceiveCallback);
privatevoidSendData(MyFriendfrd,stringdata)
byte[]msg=Encoding.UTF8.GetBytes(data);
AsyncCallbackcallback=newAsyncCallback(SendCallback);
frd.socket.BeginSend(msg,0,msg.Length,SocketFlags.None,callback,frd);
To[{0}]:
privatevoidSendCallback(IAsyncResultar)
frd.socket.EndSend(ar);
privatevoidbuttonSendMessage_Click(objectsender,EventArgse)
if(textBoxMessage.Text.Trim()=="
)
listBoxStatu.Items.Add("
不能发送空字符串!
);
textBoxMessage.Focus();
if(comboBoxClient.SelectedIndex<
0)
请在列表中选择发送对象!
inti=comboBoxClient.SelectedIndex;
SendData((MyFriend)friends[i],textBoxMessage.Text.Trim());
privatevoidbuttonStop_Click(objectsender,EventArgse)
if(!
IsStart)
listener.Stop();
listBoxStatu.Invoke(AppendString,"
已经结束了服务器的侦听!
this.buttonStart.Enabled=true;
privatevoidbuttonClear_Click(objectsender,EventArgse)
this.listBoxStatu.Items.Clear();
publicList<
getIP()
listIP=newList<
();
stringHostName=Dns.GetHostName();
//得到主机名
IPHostEntryIpEntry=Dns.GetHostEntry(HostName);
for(inti=0;
i<
IpEntry.AddressList.Length;
i++)
//从IP地址列表中筛选出IPv4类型的IP地址
//AddressFamily.InterNetwork表示此IP为IPv4,
//AddressFamily.InterNetworkV6表示此地址为IPv6类型
if(IpEntry.AddressList[i].AddressFamily==AddressFamily.InterNetwork)
listIP.Add(IpEntry.AddressList[i].ToString());
returnlistIP;
catch(Exceptionex)
MessageBox.Show("
获取本机IP出错:
+ex.Message);
listIP.Clear();
}
客户端核心代码:
packagecom.example.sockettest2;
importjava.io.IOException;
importjava.io.InputStream;
importjava.io.OutputStream;
importjava.io.UnsupportedEncodingException;
import.Socket;
import.UnknownHostException;
importandroid.os.Bundle;
importandroid.os.Handler;
importandroid.os.Message;
importandroid.app.Activity;
importandroid.view.Menu;
importandroid.view.View;
importandroid.widget.Button;
importandroid.widget.EditText;
importandroid.widget.TextView;
publicclassMainActivityextendsActivity{
privateTextViewtextReceive=null;
privateEditTexttextSend=null;
privateButtonbtnConnect=null;
privateButtonbtnSend=null;
privatestaticfinalStringServerIP="
10.0.2.2"
privatestaticfinalintServerPort=4567;
privateSocketsocket=null;
privateStringstrMessage;
privatebooleanisConnect=false;
privateOutputStreamoutStream;
privateHandlermyHandler=null;
privateReceiveThreadreceiveThread=null;
privatebooleanisReceive=false;
@Override
protectedvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textReceive=(TextView)findViewById(R.id.textViewReceive);
textSend=(EditText)findViewById(R.id.editTextSend);
btnConnect=(Button)findViewById(R.id.buttonConnect);
btnSend=(Button)findViewById(R.id.buttonSend);
//连接按钮的监听器
btnConnect.setOnClickListener(newView.OnClickListener(){
@Override
publicvoidonClick(Viewv){
//TODOAuto-generatedmethodstub
if(!
isConnect){
newThread(connectThread).start();
}
}
});
//发送按钮的监听器
btnSend.setOnClickListener(newView.OnClickListener(){
strMessage=textSend.getText().toString();
newThread(sendThread).start();
myHandler=newHandler(){
publicvoidhandleMessage(Messagemsg){
textReceive.append((msg.obj).toString());
};
//连接到服务器的接口
RunnableconnectThread=newRunnable(){
@Override
publicvoidrun(){
//TODOAuto-generatedmethodstub
try{
//初始化Scoket,连接到服务器
socket=newSocket(ServerIP,ServerPort);
isConnect=true;
//启动接收线程
isReceive=true;
receiveThread=newReceiveThread(socket);
receiveThread.start();
System.out.println("
--