Android开发菜鸟级入门5--网络编程之套接字TCP

TCP是SOCKET通信中面向连接的协议

为此,我特地先写了PC端的TCP套接字通信程序


PC服务端

#include
#include
#include
#include
#include
using namespace std;

#pragma comment(lib,"ws2_32.lib")

#define PORT 4567
#define ADDR "192.168.137.1"

int main()
{
	WSADATA wsock;
	SOCKET listensocket;
	SOCKET newconnection;
	SOCKADDR_IN serAddr;
	SOCKADDR_IN cliAddr;
	int cliAddrLen = sizeof(cliAddr);
	int nRet = 0;
	char buf[100];
	cout << "服务端";
	cout << ADDR << "-" << PORT << endl;
	//下面初始化WinSock
	cout << "初始化套接字..." << endl;
	if (WSAStartup(MAKEWORD(2, 2), &wsock) != 0)
	{
		cout << "初始化失败" << endl;
		return 0;
	}
	cout << "初始化成功" << endl;
	//下面创建监听
	cout << "创建TCP监听套接字..." << endl;
	if ((listensocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
	{
		cout << "监听创建失败" << endl;
		WSACleanup();
		return 0;
	}
	cout << "TCP监听套接字创建成功" << endl;
	serAddr.sin_family = AF_INET;
	serAddr.sin_port = htons(PORT);
	serAddr.sin_addr.S_un.S_addr = inet_addr(ADDR);
	//绑定监听套接字
	cout << "绑定监听套接字..." << endl;
	if (bind(listensocket, (SOCKADDR*)&serAddr, sizeof(serAddr)) == SOCKET_ERROR)
	{
		cout << "监听套接字绑定失败" << endl;
		closesocket(listensocket);
		WSACleanup();
		return 0;
	}
	cout << "监听套接字绑定成功" << endl;
	//创立监听
	cout << "创建监听..." << endl;
	if (listen(listensocket, 5) == SOCKET_ERROR)
	{
		cout << "监听创建失败" << endl;
		closesocket(listensocket);
		WSACleanup();
		return 0;
	}
	cout << "监听创建成功" << endl;
	//等待连接
	cout << "等待连接..." << endl;
	if ((newconnection = accept(listensocket, (SOCKADDR*)&cliAddr, &cliAddrLen)) == SOCKET_ERROR)
	{
		cout << "连接错误" << endl;
		closesocket(listensocket);
		WSACleanup();
		return 0;
	}
	cout << "连接成功!" << endl;
	cout << "连接信息:" << inet_ntoa(cliAddr.sin_addr)<<"-"<




PC客户端
#include
#include
#include
#include
#include
using namespace std;
#pragma comment(lib, "ws2_32.lib")

#define PORT 4567
#define ADDR "192.168.137.1"

int main()
{
	WSADATA wsock;
	SOCKET sconnection;
	SOCKADDR_IN serAddr;
	int nRet = 0;
	char buf[100];
	cout << "客户端"<> buf;
		cout << "发送中.." << endl;
		if ((nRet = send(sconnection, buf, strlen(buf), 0)) == SOCKET_ERROR)
		{
			cout << "发送失败" << endl;
			closesocket(sconnection);
			WSACleanup();
			return 0;
		}
		cout << "发送成功" << endl;
		if (strcmp(buf, "exit") == 0)
		{
			cout << "正常退出" << endl;
			break;
		}
		memset(buf, 0, sizeof(buf));
		cout << "等待回应..." << endl;
		if ((nRet = recv(sconnection, buf, sizeof(buf), 0)) == SOCKET_ERROR)
		{
			cout << "接收错误" << endl;
		}
		cout << "回应:";
		cout << buf << endl;
	}
	closesocket(sconnection);
	WSACleanup();
	return 0;
}

好了,现在写Android的程序
跟之前一样,我只写客户端的程序

首先在AndroidManifest.xml上加权限
android:name="android.permission.INTERNET"/>
注意要写在
的外面
然后,是一个继承View的类,我的想法是每当点一下屏幕发送一串字符

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;

/**
 * Created by xyt on 2015/10/9.
 */
public class MyView extends View{
    int door=0;
    Socket socket;

    public MyView(Context context) {
        super(context);
    }

    public boolean onTouchEvent(MotionEvent event) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                send();
                door=1;
            }
        }).start();
        return false;
    }

    protected void onDraw(Canvas canvas) {

    }

    public void send(){
        try{
            if(door==0){
                socket=new Socket("192.168.137.1", 4567);
                socket.setSendBufferSize(100);
            }
            BufferedWriter out=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            out.write("lalala");
            out.flush();
        }catch(UnknownHostException e){
            System.out.println(e);
        }catch(IOException e){
            System.out.println(e);
        }
    }

}

door记录是否是第一次点击,第一次点击就进行连接
因为执行
new Socket("192.168.138.1",4567)
的过程实际上是先发送给我的服务端一个表明地址的信息
因此这个信息只需要开始连接的时候发送就可以了,之后就不用

out.write直接将一个字符串写进发送缓存,
out.flush直接将缓存的东西全部发出,不然就是等到缓存满了再发出
当然,有一布非常必要,就是
socket.setSendBufferSize()
这个是用来调整缓存大小的
因为PC服务器的缓存大小为100byte,所以这里最好设置100byte
不要忘记,另开一个线程执执行网络任务
最后如果要关闭连接,直接out.close()就行

下面是最后步骤,在onCreate中加上
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    view=new MyView(this);
    setContentView(view);
    Log.i(Activity_ID, "onCreate!");
}

最后,我写了一个TCP通信的客户端类,包含接收和发送


package com.example.xyt.helloandroid;

import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;

/**
 * Created by xyt on 2015/10/12.
 */

public class SocketClient {

    private boolean IsConnectedFlag=false;
    private Socket socket;
    private byte[] buf=new byte[100];
    public String address="192.168.137.1";
    public int port=4567;

    public void SetServer(String in_ip,int in_port){
        address=in_ip;
        port=in_port;
    }

    //判断是否已经连接
    public boolean IsConnected(){
        return IsConnectedFlag;
    }

    //该方法是在数据通信前用的,用于连接服务器
    private void ConnectServer(){
        try{
            socket=new Socket(address,port );
            socket.setSendBufferSize(100);
        }catch(IOException e){
            System.out.println(e);
        }
    }

    //该方法用cmd去换服务器的一个回应,保存在buf中,注意调用此方法前必须先连接
    private void ChangeDataPack(String cmd){
        try{
            BufferedWriter out=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            out.write(cmd);
            out.flush();
            InputStream inputStream = socket.getInputStream();
            DataInputStream input = new DataInputStream(inputStream);
            int length=input.read(buf);
            String msg=new String(buf,0,length);
            System.out.println(msg);
        }catch(UnknownHostException e){
            System.out.println(e);
        }catch(IOException e){
            System.out.println(e);
        }
    }

    //另开线程交换数据,等待回复
    public void ExchangeData(final String in_cmd){
        new Thread(new Runnable() {
            @Override
            public void run() {
                ChangeDataPack(in_cmd);
            }
        }).start();
    }

    //另开线程等待连接
    public void Connect(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                ConnectServer();
                IsConnectedFlag=true;
            }
        }).start();
    }

    //关闭连接
    public void CloseConnection(){
        new Thread(new Runnable(){
            @Override
            public void run() {
                try{
                    socket.close();
                }catch (IOException e){
                    System.out.println(e);
                }
                IsConnectedFlag=false;
            }
        }).start();
    }
}









你可能感兴趣的:(Android开发菜鸟级入门5--网络编程之套接字TCP)