TCP-server编程

来源:互联网 发布:mac自带画图工具 编辑:程序博客网 时间:2024/06/09 15:48

一、基本解释 

      在之前的博客中我已经简单的介绍过TCP建立连接时的三次握手,以及在断开连接时的四次挥手,在此我就不再多说了,此次介绍基于TCP的套接字编程。在此类编程中会用到一些结构体以及函数,下来我简单地介绍下这些:

1.struct sockaddr_in

其结构如下

sockaddr_in(在netinet/in.h中定义):

struct sockaddr_in

{

     short sin_family;/*Address family一般来说AF_INET(地址族)PF_INET(协议族)*/

     unsigned short sin_port;/*Port number(必须要采用网络数据格式,普通数字可以用htons()函数转换成网络数据格式的数字)*/

     struct in_addr sin_addr;/*IP address in network byte order(Internet address)*/

     unsigned char sin_zero[8];/*Same size as struct sockaddr没有实际意义,只是为了 跟SOCKADDR结构在内存中对齐*/

};

2.bind函数

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

参数sockfd
指定地址与哪个套接字绑定,这是一个由之前的socket函数调用返回的套接字。调用bind的函数之后,该套接字与一个相应的地址关联,发送到这个地址的数据可以通过这个套接字来读取与使用。
参数addr
正如大多数socket接口一样,内核不关心地址结构,当它复制或传递地址给驱动的时候,它依据这个值来确定需要复制多少数据。这已经成为socket接口中最常见的参数之一了。
参数addrlen
是参数addr的大小

3.listen函数

int listen(int sock, int backlog);

sock 为需要进入监听状态的套接字,backlog 为请求队列的最大长度。

所谓被动监听,是指当没有客户端请求时,套接字处于“睡眠”状态,只有当接收到客户端请求时,套接字才会被“唤醒”来响应请求。

4.accept函数

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

sock 为服务器端套接字,addr 为 sockaddr_in 结构体变量,addrlen 为参数 addr 的长度,可由 sizeof() 求得。

accept() 返回一个新的套接字来和客户端通信,addr 保存了客户端的IP地址和端口号,而 sock 是服务器端的套接字,大家注意区分。后面和客户端通信时,要使用这个新生成的套接字,而不是原来服务器端的套接字。

二、具体编程实现

1.TCP-server

这是一个普通的TCP服务器,可以允许一个客户端进行连接

#include <stdio.h>#include <unistd.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <stdlib.h>#include <memory.h>#define MAXN_STR 40void usage(const char* proc){    printf("[%s],[localip],[localport]\n",proc);}int startup(char* ip,int port){    int sock=socket(AF_INET,SOCK_STREAM,0);    if(sock<0)    {        perror("socket\n");        return 0;    }    struct sockaddr_in local;    local.sin_family=AF_INET;    local.sin_port=htons(port);    local.sin_addr.s_addr=inet_addr(ip);    int opt=1;    setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));    if(bind(sock,(struct sockaddr*)&local,sizeof(local))<0)    {        perror("bind\n");        return 0;    }    if(listen(sock,5)<0)    {        perror("listen");        return 0;    }    return sock;}int main(int argc,char* argv[]){    if(argc!=3)    {        usage(argv[0]);        return 0;    }    int listen_sock=startup(argv[1],atoi(argv[2]));    char buf[10240];    struct sockaddr_in client;    socklen_t len=sizeof(client);    while(1)    {        int new_sock=accept(listen_sock,(struct sockaddr*)&client,&len);        if(new_sock<0)        {            perror("accept");            continue;        }        close(listen_sock);        printf("connect... ip is %s,port is %d\n ",inet_ntoa(client.sin_addr),ntohs(client.sin_port));        while(1)        {            ssize_t s=read(new_sock,buf,sizeof(buf)-1);            if(s>0)            {                buf[s]='\0';                printf("client say:%s\n",buf);                write(new_sock,buf,strlen(buf));            }            else if(s==0)            {                printf("client quit\n");                break;            }            else            {                break;            }        }        return 0;    }    return 0;}

2.TCP-server多进程版本

可以允许多个客户端同时连接


#include <stdio.h>#include <unistd.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <stdlib.h>#include <memory.h>#define MAXN_STR 40void usage(const char* proc){    printf("[%s],[localip],[localport]\n",proc);}int startup(char* ip,int port){    int sock=socket(AF_INET,SOCK_STREAM,0);    if(sock<0)    {        perror("socket\n");        return 0;    }    struct sockaddr_in local;    local.sin_family=AF_INET;    local.sin_port=htons(port);    local.sin_addr.s_addr=inet_addr(ip);    int opt=1;    setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));    if(bind(sock,(struct sockaddr*)&local,sizeof(local))<0)    {        perror("bind\n");        return 0;    }    if(listen(sock,5)<0)    {        perror("listen");        return 0;    }    return sock;}int main(int argc,char* argv[]){    if(argc!=3)    {        usage(argv[0]);        return 0;    }    int listen_sock=startup(argv[1],atoi(argv[2]));    char buf[1024];    struct sockaddr_in client;    socklen_t len=sizeof(client);    while(1)    {        int new_sock=accept(listen_sock,(struct sockaddr*)&client,&len);        if(new_sock<0)        {            perror("accept");            continue;        }printf("connect... ip is %s,port is %d \n",inet_ntoa(client.sin_addr),ntohs(client.sin_port));        pid_t id=fork();        if(id>0)        {            close(new_sock);        }        else if(id==0)        {            close(listen_sock);        if(fork() > 0)         exit(0);            while(1)            {                ssize_t s=read(new_sock,buf,sizeof(buf)-1);                if(s>0)                {                    buf[s] = 0;                    printf("client say:%s\n",buf);                    write(new_sock,buf,strlen(buf));                }                else if(s == 0)                {                    printf("client quit\n");                    break;                }                else                {                    break;                }            }            return 0;        }        else        {            perror("fork");            close(listen_sock);            return 0;        }    }    return 0;}

3.TCP-server多线程版本


#include <stdio.h>#include <sys/types.h>#include <arpa/inet.h>#include <sys/socket.h>#include <stdlib.h>#include <netinet/in.h>#include <unistd.h>#include <pthread.h>#include <string.h>void usage(char* proc){    printf("%s: [localip], [localport]\n", proc);}int startup(char* ip, int port){    int sock = socket(AF_INET, SOCK_STREAM, 0);    if(sock < 0)    {        perror("socket\n");        return 0;    }    struct sockaddr_in local;    local.sin_family = AF_INET;    local.sin_port = htons(port);    local.sin_addr.s_addr = inet_addr(ip);    int opt = 1;    setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));    if(bind(sock, (struct sockaddr*)&local, sizeof(local)) < 0)    {        perror("bind\n");        return 0;    }    if(listen(sock, 5) < 0)    {        perror("listen\n");        return 0;    }    return sock;}void *handlerRequest(void* arg){    int new_fd = (int)arg;    while(1)    {        char buf[1024];        ssize_t s = read(new_fd, buf, sizeof(buf)-1);        if(s > 0)        {            buf[s] = 0;            printf("Client: %s\n", buf);            write(new_fd, buf, strlen(buf));        }        else        {            printf("Read done..., break\n");            break;        }    }}int main(int argc, char* argv[]){    if(argc != 3)    {        usage(argv[0]);    }    int listen_sock = startup(argv[1], atoi(argv[2]));    struct sockaddr_in client;    socklen_t len = sizeof(client);    while(1)    {        int new_sock = accept(listen_sock, (struct sockaddr*)&client, &len);        if(new_sock < 0)        {            perror("accept");            continue;        }        printf("Get a new connect, %s:%d\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port));        pthread_t id;        pthread_create(&id, NULL, handlerRequest, (void *)new_sock);        pthread_detach(id);    }    return 0;}


4.TCP-client客户端部分

#include <stdio.h>#include <stdlib.h>#include <sys/types.h>#include <sys/socket.h>#include <arpa/inet.h>#include <netinet/in.h>#include <unistd.h>static void usage(const char* proc){    printf("%s:[service_ip],[service_port]\n",proc);}int main(int argc, char* argv[]){    if(argc != 3)    {        usage(argv[0]);        return 1;    }    int sock = socket(AF_INET, SOCK_STREAM, 0);    if(sock < 0)    {        perror("sock");        return 2;    }    struct sockaddr_in remote;    remote.sin_family = AF_INET;    remote.sin_port = htons(atoi(argv[2]));    remote.sin_addr.s_addr = inet_addr(argv[1]);    if(connect(sock, (struct sockaddr*)&remote, sizeof(remote)) < 0)    {        perror("connect");        return 2;    }    while(1)    {        char buf[1024];        printf("Please enter:\n");        fflush(stdout);        ssize_t s = read(0, buf, sizeof(buf)-1);        if(s > 0)        {            buf[s-1] = 0;            write(sock, buf, sizeof(buf) - 1);            ssize_t _s=read(sock, buf, sizeof(buf) - 1);            if(_s > 0)            {                buf[_s] = 0;                printf("server echo# %s\n", buf);            }        }    }    return 0;}


原创粉丝点击