您的位置:首页 > 运维架构 > Linux

简单用C#编写socket作为客户端与Linux下C++编写服务器端通信(未完善)

2013-08-05 20:52 701 查看
废话少说直接上代码:

C#客户端代码:

using System;

using System.Collections.Generic;

using System.Net;

using System.Net.Sockets;

using System.Threading;//类Thread就在此空间内,可以调用sleep函数

using System.Linq;

using System.Text;

namespace Heart

{

    class Program

    {

        private static Int32 port=3333;

        static void Main(string[] args)

        {

            byte[] data=new byte[1024];

            string str = "Hello! Welcome to C# World";

            Socket newclient=new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);

            Console.Write("Please input the server ip:");

            string ipadd=Console.ReadLine();

            IPEndPoint ie=new IPEndPoint(IPAddress.Parse(ipadd),port);//服务器端的IP和端口

            try

            {

                newclient.Connect(ie);

            }

            catch(SocketException e)

            {

                Console.WriteLine("Unable to connect to server");

                Console.WriteLine(e.ToString());

                return;

            }

            for(;;)

            {.//循环发送和接收

                Thread.Sleep(5000);//睡眠5秒钟

                data=Encoding.ASCII.GetBytes(str);

                newclient.Send(data, data.Length, SocketFlags.None);//发送信息

                int recv = newclient.Receive(data);

                string stringdata = Encoding.ASCII.GetString(data, 0, recv);

                Console.WriteLine("received:" + stringdata);

            }

        }

    }

}

服务器端代码:

#include<iostream>

#include<stdlib.h>

#include<stdio.h>

#include<sys/socket.h>

#include<sys/epoll.h>

#include<netinet/in.h>

#include<arpa/inet.h>

#include<fcntl.h>

#include<errno.h>

#include<unistd.h>

#include<string.h>

#include<netinet/tcp.h>

#define SERVER_PORT 3333

#define LENGTH_OF_LISTEN_QUEUE 20

#define MAXBUF 100

using namespace std;

int EstablishServer(struct sockaddr_in * addr,socklen_t addrLen,int port);

void * HeartService(void * arg);

void setnonblocking(int sock);

int main()

{

    struct sockaddr_in server_addr,client_addr;

    int serverFd,clientFd;

    socklen_t clientLen=sizeof(struct sockaddr);

    //建立socket连接

    serverFd=EstablishServer(&server_addr,sizeof(server_addr),SERVER_PORT);

    if(serverFd==-1)

    {

        cout<<"serverFd create failed!"<<endl;

        exit(1);

    }

    for(;;)

    {

        //等待连接的请求

        if((clientFd=accept(serverFd,(struct sockaddr *)&client_addr,&clientLen))<0)

        {

            perror("accept wrong !:");

            exit(1);

        }

        cout<<"----------------------------------------------------------------"<<endl;

        printf("accept from %s:%d\n",inet_ntoa(client_addr.sin_addr),client_addr.sin_port);

        pthread_t clientTid;

        int pthrst=pthread_create(&clientTid,NULL,HeartService,(void *)&clientFd);

        if(pthrst!=0)

        {

            perror("pthread_create wrong ! :");

        }      

    }

    return 0;

}

//建立服务端socket的通信,绑定端口

int EstablishServer(struct sockaddr_in * addr,socklen_t addrLen,int port)

{

    int listenfd=socket(AF_INET,SOCK_STREAM,0);

    if(listenfd<0)

    {

        perror("listenfd socket error");

        return -1;

    }

    bzero(addr,addrLen);

    addr->sin_family=AF_INET;

    addr->sin_addr.s_addr=htonl(INADDR_ANY);

    addr->sin_port=htons(port);

    if(bind(listenfd,(struct sockaddr *)addr,addrLen)<0)

    {

        perror("bind error");

        return -1;

    }

    if(listen(listenfd,LENGTH_OF_LISTEN_QUEUE)<0)

    {

        perror("listen error");

        return -1;

    }

    return listenfd;

}

//心跳机制线程

void *HeartService(void * arg)

{

    //获得自身的线程号

    pthread_t tid=pthread_self();

    //获得传送过来的clientFd

    int clientFd=*(int *)arg;

    cout<<"New thread create,the tid is "<<tid<<" the clientFd is "<<clientFd<<endl;

    int sockfd;//用于获取epoll函数的fd值

    char buf[MAXBUF];

    int epfd,nfds,n,m,count=0;

    struct epoll_event ev,events[20];//声明epoll_event结构体的变量,ev用于注册事件,events数组用于回传要处理的事件

    int keepAlive=1;//开启keepalive属性

    int keepIdle=5;//如该连接在5秒内没有任何数据往来,则进行探测

    int keepInterval=2;//探测时发包的时间间隔为2秒

    int keepCount=3;//探测尝试的次数。如果第1次探测包就收到响应了,则后2次的不再发送

    setsockopt(clientFd,SOL_SOCKET,SO_KEEPALIVE,(void *)&keepAlive,sizeof(keepAlive));

    setsockopt(clientFd,SOL_TCP,TCP_KEEPIDLE,(void *)&keepIdle,sizeof(keepIdle));

    setsockopt(clientFd,SOL_TCP,TCP_KEEPINTVL,(void *)&keepInterval,sizeof(keepInterval));

    setsockopt(clientFd,SOL_TCP,TCP_KEEPCNT,(void *)&keepCount,sizeof(keepCount));

    //把客户端的socket设置为非阻塞方式

    setnonblocking(clientFd);

    epfd=epoll_create(256);//生成epoll专用的文件描述符,指定生成描述符的最大范围为256

    ev.data.fd=clientFd;

    ev.events=EPOLLIN|EPOLLET;

    epoll_ctl(epfd,EPOLL_CTL_ADD,clientFd,&ev);

    for(;;)

    {

        nfds=epoll_wait(epfd,events,20,-1);

        cout<<"the tid is "<<tid<<" the clientFd is "<<clientFd<<" the count is "<<++count<<endl;

        for(int i=0;i<nfds;++i)

        {

            if(events[i].events&EPOLLIN)

            {

                if((sockfd=events[i].data.fd)<0)

                {

                    cout<<"It is recevied continue!"<<endl;

                    continue;//因为下面设置了,所以这里考虑了

                }

                if((n=recv(sockfd,buf,MAXBUF,0))<0)

                {

                    if(errno==ECONNRESET)//表示连接被重置了,已经无效了,关闭它,删除它

                    {

                        printf("It is ECONNRESET:%s\n",strerror(ECONNRESET));

                        epoll_ctl(epfd,EPOLL_CTL_DEL,sockfd,NULL);//可以把这个sockfd从epfd队列中删除了

       

                    }

                    else if(errno==ETIMEDOUT)

                    {

                        cout<<"Ha Ha you want ETIMEDOUT"<<endl;

 

                    }

                    else

                        cout<<"read error!"<<endl;  //其他错误

                    epoll_ctl(epfd,EPOLL_CTL_DEL,sockfd,NULL);

                    return 0;

                }

                else if(n==0)//有读事件触发,但是read返回0,所以是对面已经关闭sockfd了

                {

                    cout<<"n=0 ,sockfd is "<<sockfd<<" and tid is "<<tid<<endl;

                    epoll_ctl(epfd,EPOLL_CTL_DEL,sockfd,NULL);

                    close(sockfd);

                }

                else

                {

                    buf
='\0';

                    cout<<"received:"<<buf<<" and sockfd is "<<sockfd<<endl;

                    ev.data.fd=sockfd;

                    ev.events=EPOLLOUT|EPOLLET;

                    epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev);

                }

            }

            else if(events[i].events&EPOLLOUT)

            {

                sockfd=events[i].data.fd;

                m=strlen(buf);

                cout<<"m is "<<m<<endl;

                if(write(sockfd,buf,m)<0)

                {

                    cout<<"write wrong ! and sockfd is:"<<sockfd<<endl;

                }

                else

                {

                    cout<<"send success and buf is "<<buf<<endl;

                }

                ev.data.fd=sockfd;

                ev.events=EPOLLIN|EPOLLET;

                epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev);//修改sockfd上要处理的事件为EPOLLIN,下次监听读事件

            }

        }

    } 

}

void setnonblocking(int sock)

{

    int opts;

    opts=fcntl(sock,F_GETFL);//把sock的属性查询出来,存到opts中

    if(opts<0)

    {

        perror("fcntl(sock,GETFL)");

        exit(1);

    }

    opts=opts|O_NONBLOCK;//把opts中的某一位O_NONBLOCK置为生效

    if(fcntl(sock,F_SETFL,opts)<0)

    {

        perror("fcntl(sock,SETFL,opts)");

        exit(1);

    }

}

记得要关闭服务器端的防火墙
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: