现在的位置: 首页 > 综合 > 正文

Socket编程实践(3)

2017年10月06日 ⁄ 综合 ⁄ 共 4243字 ⁄ 字号 评论关闭

Socket 基础API实践(2)--实现回射服务器

accept函数

功能:从已完成连接队列返回第一个连接,如果已完成连接队列为空,则阻塞。

原型

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

参数

    sockfd:服务器套接字

    addr:将返回对等方的套接字地址

    addrlen:返回对等方的套接字地址长度

 

返回值

       On  success, these system calls return a nonnegative integer that is a descriptor for the accepted socket.  On error, -1 is returned, 

and errno is set appropriately.

 

Man-Page说明

    The  accept()  system  call  is  used  with  connection-based  socket types (SOCK_STREAM, SOCK_SEQPACKET).  It extracts the first connection request on the queue of  pending  connections  for the listening socket, sockfd, creates a new connected socket, and returns a new file descriptor referring to that socket.  The newly created socket  is  not  in  the listening state.  The original socket sockfd is unaffected by this call.

//server端代码
#include "commen.h"

int main()
{
    int sockfd = socket(AF_INET,SOCK_STREAM,0);
    if (sockfd == -1)
    {
        err_exit("socket error");
    }

    struct sockaddr_in serverAddr;
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(8002);
    serverAddr.sin_addr.s_addr = INADDR_ANY;    //绑定本机的任意一个IP地址
    //serverAddr.sin_addr.s_addr = inet_addr("10.255.218.20");
    if (bind(sockfd,(struct sockaddr *)&serverAddr,sizeof(serverAddr)) == -1)
    {
        err_exit("bind error");
    }

    //一旦调用了listen,则sockfd编程被动套接字:等待客户端的连接(只能接受连接,不能发送连接)
    if (listen(sockfd,SOMAXCONN) == -1)
    {
        err_exit("listen error");
    }

    struct sockaddr_in peerAddr;
    socklen_t peerLen;
    //注意:也要强制类型转换为通用地址结构
    //accept返回一个与server对等的套接字,它是一个主动套接字
    int peerSockfd = accept(sockfd, (struct sockaddr *)&peerAddr,&peerLen);
    if (peerSockfd == -1)
    {
        err_exit("accept error");
    }

    //打印客户信息
    cout << "Client:" << endl;
    cout << "\tsin_port: " << ntohs(peerAddr.sin_port) << endl;
    cout << "\tsin_addr: " << inet_ntoa(peerAddr.sin_addr) << endl;
    cout << "\tsocket: " << peerSockfd << endl;


    char buf[BUFSIZ];
    memset(buf,0,sizeof(buf));
    ssize_t readCount = 0;
    while ((readCount = read(peerSockfd,buf,sizeof(buf))) >= 0)
    {
        //如果在读取数据的过程中,read返回0,则说明对方已经关闭连接
        if (readCount == 0)
        {
            err_exit("read peerSockfd error");
        }
        if (write(peerSockfd,buf,readCount) == -1)
        {
            err_exit("write peerSockfd error");
        }
        buf[readCount] = '\0';
        fputs(buf,stdout);
        memset(buf,0,sizeof(buf));
    }

  close(peerSockfd);
    close(sockfd);
    return 0;
}

connect函数

功能:建立一个连接至addr所指定的套接字

原型

int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

参数

    sockfd:未连接套接字

    addr:要连接的套接字地址

    addrlen:第二个参数addr长度

返回值:

   成功返回0,失败返回-1并设置errno

 

DESCRIPTION

       The  connect()  system call connects the socket referred to by the file descriptor sockfd to the address specified by addr.  The addrlen argument specifies the size of addr.   The format  of  the  address in addr is determined by the address space of the socket sockfd; see socket(2) for further details.

//client端代码
#include "commen.h"

int main()
{
    int sockfd = socket(AF_INET,SOCK_STREAM,0);
    if (sockfd == -1)
    {
        err_exit("socket error");
    }

    //填写好服务器地址及其端口号
    struct sockaddr_in serverAddr;
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(8002);
    //如果只有一台主机的话,在IP地址处可以填写127.0.0.1(回环地址)
    serverAddr.sin_addr.s_addr = inet_addr("192.168.139.137");
    //连接server
    if (connect(sockfd,(struct sockaddr *)&serverAddr,sizeof(serverAddr)) == -1)
    {
        err_exit("connect error");
    }

    char sendBuf[BUFSIZ] = {0};
    char recvBuf[BUFSIZ] = {0};
    int readCount = 0;

    while (fgets(sendBuf,sizeof(sendBuf),stdin) != NULL)
    {
        //向server发送数据
        if (write(sockfd,sendBuf,strlen(sendBuf)) == -1)
        {
            err_exit("write socket error");
        }
        //从server接收数据
        if ((readCount = read(sockfd,recvBuf,sizeof(recvBuf))) < 0)
        {
            err_exit("read socket error");
        }
        if (recvBuf[readCount] == '\n')
        {
            recvBuf[readCount] = '\0';
        }
        //将其回写到终端
        write(STDOUT_FILENO,recvBuf,strlen(recvBuf));

        memset(sendBuf,0,sizeof(sendBuf));
        memset(recvBuf,0,sizeof(recvBuf));
    }

    close(sockfd);
    return 0;
}

1-commen.h代码

#ifndef COMMEN_H_INCLUDED
#define COMMEN_H_INCLUDED

#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/msg.h>
#include <sys/sem.h>
#include <sys/socket.h>

#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>

#include <arpa/inet.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#include <iostream>
using namespace std;


void err_exit(std::string str)
{
    perror(str.c_str());
    exit(EXIT_FAILURE);
}

#endif // COMMEN_H_INCLUDED

2-Makefile

CC = g++ 
CPPFLAGS = -Wall -g -pthread

BIN = server client
SOURCES = $(BIN.=.cpp)

.PHONY: clean all 

all: $(BIN)

$(BIN): $(SOURCES)

clean:
-rm -rf $(BIN) bin/ obj/ core

3-netstat 命令

抱歉!评论已关闭.