Linux下TCP/socket编程

写在前面:本博客为本人原创,严禁任何形式的转载!本博客只允许放在博客园(.cnblogs.com),如果您在其他网站看到这篇博文,请通过下面这个唯一的合法链接转到原文!

本博客全网唯一合法URL:http://www.cnblogs.com/acm-icpcer/p/9073801.html

(本篇博客参考了:https://www.cnblogs.com/xiaojiang1025/archive/2016/10/11/5950458.html,源码为我自己所写)

基本模型:

 

核心代码:

#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
//服务器:  

socket()              //创建socket                    
struct sockaddr_in    //准备通信地址      
bind()                //绑定socket和addr
listen()              //创建listening socket
accept()              //创建connect socket
send()/recv()         //进行通信            
close()               //关闭socket            

//客户端:

socket()              //创建socket
准备通信地址:服务器的地址
connect()             //链接socket和通信地址
send()/recv()         //进行通信
close()               //关闭socket

关键函数解释:

bind()

//把通信地址和socket文件描述符绑定,用在服务器端,成功返回0,失败返回-1设errno

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

sockfd: socket文件的fd(returned by socket())

addr: 需要强制类型转换成socketaddr_un或soketaddr_in, 参见上

addrlen: 通信地址的大小, 使用sizeof();

 

listen()

//创建侦听socket,把sockfd标记的socket标记为被动socket,被动socket表示这个socket只能用来接收即将到来的连接请求,不再用于读写操作和通信,接收连接请求的是accept()

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

int listen(int sockfd, int backlog);

backlog:排队等待“被响应”连接请求队列的最大长度 eg: 接待室的最大长度

 

accept()

//创建连接socket,返回连接socket的文件描述符,成功返回文件描述符,失败返回-1设errno

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

addr : 结构体指针, 用于带出客户端的通信地址

addlen : 结构体指针, 用于带出通信地址的大小

ATTENTION: listen()把socket()创建的sockfd变为listening socket, 负责侦听哪个client连接上了(即不但要知道连上没, 还要知道谁连上了, 这个SOCK_STREAM的socket有这个能力), accept()提取排队中的最上面的一个client, 给它一个conneted socket, 这样这个client就可以和server沟通了, 就是说这里有两个socket, 一个负责侦听一个负责通信

 

send()

//向指定的socket发送指定的数据,成功返回实际发送数据的大小,失败返回-1设errno

ssize_t send(int sockfd, const void *buf, size_t len, int flags);

sockfd: 用于通信的socket描述符(returned by accept())

buf : 被发送数据的缓冲区首地址

len : 被发送数据的大小

flags: 发送的标志, 如果给0等同于write()

 

recv()

//从指定的socket接收数据,成功返回接收的数据的大小,失败返回-1设errno

ssize_t recv(int sockfd, void *buf, size_t len, int flags);

sockfd: 用于通信的socket描述符(returned by accept())

buf: 接收数据的缓冲区首地址

len: 接收数据的大小

flags: 发送的标志, 如果给0等同于read()

 

connect()

//初始化一个socket的连接,用在客户端,成功返回0,失败返回-1设errno

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

sockfd: socket文件的fd(returned by socket())

addr: 需要强制类型转换成socketaddr_un或soketaddr_in, 参见上

addrlen: 通信地址的大小, 使用sizeof();

源代码:

 

1、client端:

/*
./server (local ip) 7575
          自己ip    端口
*/
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <resolv.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>

#define MAXBUF 1024

int main(int argc, char **argv)
{
    int sockfd, len;
    struct sockaddr_in dest;
    char buffer[MAXBUF + 1];
    if (argc != 3) 
    {
    printf(" error format,it must be:\n\t\t%s IP port\n",argv[0]);
    exit(EXIT_FAILURE);
    }

    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
    perror("Socket");
    exit(errno);
    }
    printf("socket created\n");


    bzero(&dest, sizeof(dest));
    dest.sin_family = AF_INET;
    dest.sin_port = htons(atoi(argv[2]));
    if (inet_aton(argv[1], (struct in_addr *) &dest.sin_addr.s_addr) == 0) 
    {
    perror(argv[1]);
    exit(errno);
    }
    if (connect(sockfd, (struct sockaddr *) &dest, sizeof(dest))==-1) 
    {
    perror("Connect ");
    exit(errno);
    }
    printf("server connected\n");

    while (1) {
    bzero(buffer, MAXBUF + 1);
    len = recv(sockfd, buffer, MAXBUF, 0);
    if (len > 0)
        printf("recv successful:'%s',%d byte recv\n",buffer, len);
    else {
        if (len < 0)
        printf("send failure,errno code is %d,err message is '%s'\n",errno, strerror(errno));
        else
        printf("the other one close ,quit\n");
        break;
    }
    bzero(buffer, MAXBUF + 1);
    printf("pls send message to send:");
    fgets(buffer, MAXBUF, stdin);
    if (!strncasecmp(buffer, "quit", 4)) 
    {
        printf(" i will quit!\n");
        break;
    }
    len = send(sockfd, buffer, strlen(buffer) - 1, 0);
    if (len < 0) 
    {
        printf("message '%s' send failure,errno code is %d,errno message is '%s'\n",buffer, errno, strerror(errno));
        break;
    } else
        printf("message:%s\tsend successful,%dbyte send!\n",buffer, len);
    }
    close(sockfd);
    return 0;
}

2、server端:

/*
./server (local ip) 7575 5
          自己ip   端口  等待队列大小
ifconfig -a
*/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <unistd.h>
#include <arpa/inet.h>

#define MAXBUF 1024

int main(int argc, char *argv[])
{
    int pid;
    
    int sockfd, new_fd;
    socklen_t len;
    struct sockaddr_in my_addr, their_addr;
    unsigned int myport, lisnum;
    char buf[MAXBUF + 1];

    if (argv[2])
        myport = atoi(argv[2]);
    else
        myport = 7575;

    if (argv[3])
        lisnum = atoi(argv[3]);
    else
        lisnum = 5;

    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) 
    {
        perror("socket");
        exit(EXIT_FAILURE);
    }
    
    bzero(&my_addr, sizeof(my_addr));
    my_addr.sin_family = AF_INET;
    my_addr.sin_port = htons(myport);
    if (argv[1])
    my_addr.sin_addr.s_addr = inet_addr(argv[1]);
    else
    my_addr.sin_addr.s_addr = INADDR_ANY;

    if (bind(sockfd, (struct sockaddr *) &my_addr, sizeof(struct sockaddr))== -1) 
    {
        perror("bind");
        exit(EXIT_FAILURE);
    }

    if (listen(sockfd,lisnum ) == -1) 
    {
        perror("listen");
        exit(EXIT_FAILURE);
    }
    printf("wait for connect\n");    
    len = sizeof(struct sockaddr);
    if ((new_fd =accept(sockfd, (struct sockaddr *) &their_addr,&len)) == -1) 
    {
        perror("accept");
        exit(EXIT_FAILURE);
    } 
    else
        printf("server: got connection from %s, port %d, socket %d\n",inet_ntoa(their_addr.sin_addr),ntohs(their_addr.sin_port), new_fd);
         
    while (1) 
    {
          printf("newfd=%d\n",new_fd);
        bzero(buf, MAXBUF + 1);
        printf("input the message to send:");
      fgets(buf, MAXBUF, stdin);
      if (!strncasecmp(buf, "quit", 4)) 
      {
        printf("i will close the connect!\n");
        break;
      }
      len = send(new_fd, buf, strlen(buf) - 1, 0);
      if (len > 0)
        printf("message:%s\t send sucessful,send %dbyte!\n",buf, len);
      else 
      {
        printf("message'%s' send failure!errno code is %d,errno message is '%s'\n",buf, errno, strerror(errno));
        break;
      }
      bzero(buf, MAXBUF + 1);

      len = recv(new_fd, buf, MAXBUF, 0);
      if (len > 0)
        printf("message recv successful :'%s',%dByte recv\n",buf, len);
      else 
      {
        if (len < 0)
            printf("recv failure!errno code is %d,errno message is '%s'\n",errno, strerror(errno));
        else
            printf("the other one close quit\n");
        break;
      }
    }
    close(new_fd);
      close(sockfd);
        return 0;
}

运行示例:

 

PS(被蔡总玩坏了的tcp,23333):

tz@COI HZAU

2018/5/22

猜你喜欢

转载自www.cnblogs.com/acm-icpcer/p/9073801.html