套接字---TCP传输控制协议通讯

1561@TOC

一、TCP

简单通讯

一;客户端访问Server

telnet 127.0.0.1 8080
netstat nltp |grep 8080

server.hpp

#ifndef __TCP_SERVER_H__
#define __TCP_SERVER_H__

#include <iostream>
#include <string>
#include <cstdlib>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

//using namespace std;

#define BACKLOG 5

class tcpServer{
   
    private:
        int port;
        int lsock; //监听套接字
    public:
        tcpServer(int _port):port(_port), lsock(-1)
        {
   }
        void initServer()
        {
   
            lsock = socket(AF_INET, SOCK_STREAM, 0);
            if(lsock < 0){
   
                std::cerr << "socket error" << std::endl;
                exit(2);
            }
            struct sockaddr_in local;
            local.sin_family = AF_INET;
            local.sin_port = htons(port);
            local.sin_addr.s_addr = htonl(INADDR_ANY); // 区别 UDP :... = INADDR_ANY

            if(bind(lsock, (struct sockaddr*)&local, sizeof(local)) < 0){
   
                std::cerr << "bind error" << std::endl;
                exit(3);
            }
			//============新增=============================
			//这个listen自动接收lsock文件里的连接,之后使用accept接收连接,listen仅适用于SOCK_STREAM、SOCK_SEQPACKET等;
			//BACKLOG 指链接数队列长度限制,如果队列满了,用户将会接收到错误;
            if(listen(lsock, BACKLOG) < 0){
    //成功返回0 失败返回-1
                std::cerr << "bind error" << std::endl;
                exit(4);
            }
			//=============================================
        }
        void service(int sock)
        {
   
            char buffer[1024];
            while(true){
   
                //read or write -> ok!
                ssize_t s = recv(sock, buffer, sizeof(buffer)-1, 0);
                if(s > 0){
   
                    buffer[s] = 0;
                    std::cout << "client# " << buffer << std::endl;
                    send(sock, buffer, strlen(buffer), 0);   //区别 UDP
				//用于向另一个套接字传递消息 Send仅仅用于连接套接字,而 sendto 和 sendmsg 可用于任何情况下.
				// sendto(sock, echo.c_str(), echo.size(), 0,(struct sockaddr*)&end_point, len);
                }
            }
        }
        void start()
        {
   
            sockaddr_in endpoint;
            while(true){
   
                socklen_t len = sizeof(endpoint);
				//accept 在一个套接字上接收一个连接,从lsock(未完成连接队列)里取一个连接,创建
				//一个属性相同的套接字并分配一个文件描述符。
                int sock = accept(lsock, (struct sockaddr*)&endpoint, &len);
                if(sock < 0){
   
                    std::cerr << "accept error" << std::endl;
                    continue;
                }
                std::cout << "get a new link ..." <<std::endl;
                service(sock);
            }
        }
        ~tcpServer()
        {
   }
};
#endif

server.cc

#include "tcpServer.hpp"

static void Usage(std::string proc)
{
   
    std::cout << "Usage: " << std::endl;
    std::cout << '\t' << proc << " port" << std::endl;
}

int main(int argc, char *argv[])
{
   
    if(argc != 2){
   
        Usage(argv[0]);
        exit(1);
    }

    tcpServer * tp = new tcpServer(atoi(argv[1]));
    tp->initServer();
    tp->start();

    delete tp;
    return 0;
}

二;多进程版服务器;

Makefile

FLAG=-std=c++11 -lpthread

.PHONY:all
all:tcpClient tcpServer

tcpClient:tcpClient.cc
	g++ -o $@ $^ $(FLAG) -static
tcpServer:tcpServer.cc
	g++ -o $@ $^ $(FLAG) -g

.PHONY:clean
clean:
	rm -f tcpClient tcpServer

server.hpp

#ifndef __TCP_SERVER_H__
#define __TCP_SERVER_H__

#include <iostream>
#include <unistd.h>
#include <cstdlib>
#include <string>
#include <cstdlib>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#include <pthread.h>
#include "ThreadPool.hpp"
//using namespace std;

#define BACKLOG 5

class tcpServer{
   
    private:
        int port;
        int lsock; //监听套接字
        ThreadPool *tp;
    public:
        tcpServer(int _port)
            :port(_port), lsock(-1),tp(nullptr)
        {
   }
        void initServer()
        {
   
            signal(SIGCHLD, SIG_IGN);  //信号;为了不产生僵尸进程,会自动清理掉,不会通知父进程
            lsock = socket(AF_INET, SOCK_STREAM, 0);
            if(lsock < 0){
   
                std::cerr << "socket error" << std::endl;
                exit(2);
            }
            struct sockaddr_in local;
            local.sin_family = AF_INET;
            local.sin_port = htons(port);
            local.sin_addr.s_addr = htonl(INADDR_ANY);

            if(bind(lsock, (struct sockaddr*)&local, sizeof(local)) < 0){
   
                std::cerr << "bind error" << std::endl;
                exit(3);
            }

            if(listen(lsock, BACKLOG) < 0){
   
                std::cerr << "bind error" << std::endl;
                exit(4);
            }
            //tp = new ThreadPool();
            //tp->ThreadPoolInit();
        }
        //BUG
        void service(int sock)
        {
   
            char buffer[1024];
            while(true){
   
                //read or write -> ok!
                size_t s = recv(sock, buffer, sizeof(buffer)-1, 0); //The return value will be 0 when the peer has performed an orderly shutdown.
                if(s > 0){
   
                    buffer
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值