C,C++,C#,java,python编写简单的echo服务程序

echo网络服务做为初步网络编程的基础。

下面的echo服务,部分是以前写的,部分今天写的,做复习及以后备查之用。

监听本地的8880端口。均以telnet为客户端做的测试(telnet 127.0.0.1 8880)。

检查到换行时,就把一行数据返回给客户端。


C版:

#include <stdio.h>
#include <WinSock2.h>
#pragma comment(lib,"ws2_32.lib")

int _tmain(int argc, _TCHAR* argv[])
{
	//初始化
	WORD sockVersion = MAKEWORD(2, 2);
	WSADATA wsaData;
	if (WSAStartup(sockVersion, &wsaData) != 0){
		printf("init error");
		return 0;
	}
	//创建socket
	SOCKET slisten = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (slisten == INVALID_SOCKET){
		printf("socket error");
		WSACleanup();
		return 0;
	}

	sockaddr_in sin;
	sin.sin_family = AF_INET;
	sin.sin_port = htons(8880);
	sin.sin_addr.S_un.S_addr = INADDR_ANY;
	//绑定IP和端口
	if (bind(slisten, (LPSOCKADDR)&sin, sizeof(sin)) == SOCKET_ERROR){
		printf("bind error");
		WSACleanup();
		return 0;
	}
	//监听端口
	if (listen(slisten,5)==SOCKET_ERROR)
	{
		printf("listen error!");
		WSACleanup();
		return 0;
	}

	SOCKET sClient;
	sockaddr_in remoteAddr;
	int nAddrlen = sizeof(remoteAddr);
	char revData[128];
	printf("wait for client connection...\r\n");
	//等待连接
	sClient = accept(slisten, (SOCKADDR*)&remoteAddr, &nAddrlen);
	if (sClient == INVALID_SOCKET){
		printf("accept error!");
		WSACleanup();
		return 0;
	}
	printf("accept client: %s:%d\r\n", inet_ntoa(remoteAddr.sin_addr),ntohs(remoteAddr.sin_port));

	int offsetLen = 0;
	int ret = 0;
	//接收数据
	while (true){
		ret = recv(sClient, revData+offsetLen, 128-offsetLen, 0);
		if (ret > 0){
			offsetLen += ret;
			if (offsetLen >= 128 || revData[offsetLen - 1] == 0x0a){
				revData[offsetLen - 1] = 0x00;
				break;
			}
		}
		else{
			break;
		}
	}
	
	printf("recive message: %s", revData);

	//发送数据
	send(sClient, revData, strlen(revData), 0);

	//释放资源
	closesocket(sClient);
	closesocket(slisten);
	WSACleanup(); 

	return 0;
}

C++版(利用的boost的asio库,编译需要添加boost到路径中去):

#include "stdafx.h"
#include <iostream>
#include <string>
#include <sstream>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/asio.hpp>

using boost::asio::ip::tcp;

class EchoConection
	:public boost::enable_shared_from_this<EchoConection>
{
public:
	typedef boost::shared_ptr<EchoConection> pointer;
	static pointer create(boost::asio::io_service& io_service)
	{
		return pointer(new EchoConection(io_service));
	}
	tcp::socket & socket()
	{
		return socket_;
	}
	void start()
	{
		std::cout<<socket_.remote_endpoint().address()<<":";
		std::cout<<socket_.remote_endpoint().port()<<" conction\n";
		boost::system::error_code error;
		handle_read(error,0);
	}
private:
	EchoConection(boost::asio::io_service& io_service)
		:socket_(io_service)
	{
	}
	void handle_write(const boost::system::error_code &error ,size_t transftran)
	{
		if (!error)
		{
			if (buf_[0]=='\n')
			{
				std::cout<<"recive message: "<<ss_.str()<<std::endl;
				ss_<<"\n";
				boost::asio::async_write(socket_,boost::asio::buffer(ss_.str()),
					boost::bind(&EchoConection::handle_read,
					shared_from_this(),
					boost::asio::placeholders::error,
					boost::asio::placeholders::bytes_transferred));
				ss_.str("");
			}
			else if(buf_[0]== 'q')
			{
				std::cout<<socket_.remote_endpoint().address()<<":";
				std::cout<<socket_.remote_endpoint().port()<<" realse conction\n";
				socket_.close();
			}
			else
			{
				ss_<<buf_[0];
				boost::system::error_code error;
				handle_read(error,0);
			}

		}
		else
		{
			std::cout<<error.message()<<std::endl;
		}

	}
	void handle_read(const boost::system::error_code & error ,size_t transftran)
	{
		if (!error)
		{
			boost::asio::async_read(socket_,boost::asio::buffer(buf_),
				boost::asio::transfer_at_least(1),
				boost::bind(&EchoConection::handle_write,
				shared_from_this(),
				boost::asio::placeholders::error,boost::asio::placeholders::bytes_transferred));
		}
		else
		{
			std::cout<<error.message()<<std::endl;
		}

	}
	tcp::socket socket_;
	std::stringstream ss_;
	char buf_[1];
};
class EchoService
{
public:
	EchoService(boost::asio::io_service& io_service)
		:acceptor_(io_service,tcp::endpoint(tcp::v4(),8880))
	{
		start_accept();
	}
private:
	void start_accept()
	{
		EchoConection::pointer new_connection = 
			EchoConection::create(acceptor_.get_io_service());

		acceptor_.async_accept(new_connection->socket(),
			boost::bind(&EchoService::handle_accept,this,new_connection,
			boost::asio::placeholders::error));
	}
	void handle_accept(EchoConection::pointer new_connection,
		const boost::system::error_code& error)
	{
		if (!error)
		{
			new_connection->start();
		}
		start_accept();
	}

	tcp::acceptor acceptor_;
};

int RunEchoService_main()
{
	try
	{
		boost::asio::io_service io_service;
		EchoService server(io_service);
		io_service.run();
	}
	catch(std::exception & e)
	{
		std::cerr<<e.what()<<std::endl;
	}
	return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
	RunEchoService_main();
	return 0;
}

C#版:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;

namespace EchoService
{
    class Program
    {
        static void Main(string[] args)
        {
            int port = 8880;
            string host = "127.0.0.1";
            IPAddress ip = IPAddress.Parse(host);
            IPEndPoint ipe = new IPEndPoint(ip, port);
            Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            s.Bind(ipe);
            s.Listen(0);
            Console.WriteLine("wait for client connection...");
            Socket csocket = s.Accept();
            Console.WriteLine("accept client:   "+csocket.RemoteEndPoint.ToString());
            string recvStr = "";
            byte[] recvBytes = new byte[128];
            int offsetLen = 0;
            while(true){
                csocket.Receive(recvBytes, offsetLen, 1,SocketFlags.None);
                offsetLen++;
                if (offsetLen >= 128 || (recvBytes[offsetLen - 1] == 0x0d))
                {
                    break;
                }
            }
            recvStr += Encoding.ASCII.GetString(recvBytes, 0, offsetLen-1);
            Console.WriteLine("recive message:   {0}", recvStr);
            csocket.Send(Encoding.ASCII.GetBytes(recvStr));
            csocket.Close();
            Console.ReadLine();
        }
    }
}

java版:

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;

public class SimpleEchoService {
	public static void main(String[] args) throws IOException {
		String host = "127.0.0.1";
		int port = 8880;
		ServerSocket ss = new ServerSocket();
		ss.bind(new InetSocketAddress(host,port));
		System.out.println("wait for client connection...");
		Socket cs = ss.accept();
		System.out.println("accept client:  "+cs.getRemoteSocketAddress());
		OutputStream os = cs.getOutputStream();
		InputStream is = cs.getInputStream();
		byte [] bys = new byte[128];
		int offsetLen=0;
		while(true){
			is.read(bys, offsetLen, 1);
			offsetLen++;
			if(offsetLen >= 128 || bys[offsetLen-1]==0x0d){
				break;
			}
		}
		System.out.println("revice message: "+new String(bys));
		
		os.write(bys);
		
		is.close();
		os.close();
		cs.close();
		ss.close();
	}
}

python版:

import socket
import sys
sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server_address = ('localhost',8880);
print >>sys.stderr, 'starting up on %s port %s' % server_address
sock.bind(server_address)
sock.listen(1)

while True:
    print >> sys.stderr, 'waiting for a connection'
    connection,client_address = sock.accept()
    try:
        print >>sys.stderr,'connectino from',client_address  
        line="";
        while True:
            data = connection.recv(16)
            if data=="\r\n":
                break;
            line=line+data;
        print >>sys.stderr,"received message: %s " % line
        if line:
            print >>sys.stderr,"sending data back to the client"
            connection.sendall(line)
        else:
            print >> sys.stderr,"no data from",client_address
            break;            
    finally:
        connection.close()

总结:

1,python,java,C#版代码都比较简单易懂。大概流程就是构造socket,绑定,监听,接收数据,发送数据,关闭资源

2,C写的比较长,但是它们基础,因为window系统中,java,C#,python,基本上都是调用的WSA系列函数接口。

3,C++写的比较复杂,因用用的asio库, 就是一个connection对象,一个service对象,利用回调函数循环监听接收发送数据,是更高层次的封装。



你可能感兴趣的:(C++,python,网络编程)