>

TCP实战练习,socket互连网编制程序基础

- 编辑:www.bifa688.com -

TCP实战练习,socket互连网编制程序基础

   用socket进行网络开发需了解服务器和客户端的Socket原语,每个原语在不同的高级语言中都有相应的实现方式。TCP的Socket原语如下:

必发88手机版,Socket TCP网络通信编程

Linux socket网络编程基础 tcp协议和udp协议,socketudp

Socket TCP网络通信编程

首先,服务器端需要做以下准备工作:

  (1)调用socket()函数。建立socket对象,指定通信协议。

  (2)调用bind()函数。将创建的socket对象与当前主机的某一个IP地和端口绑定。

  (3)调用listen()函数。使socket对象处于监听状态,并设置监听队列大小。

客户端需要做以下准备工作:

  (1)调用socket()函数。建立socket()对象,指定相同通信协议。

  (2)应用程序可以显式的调用bind()函数为其绑定IP地址和端口,当然,也可以将这工作交给TCP/IP协议栈。

接着建立通信连接:

  (1)客户端调用connect()函数。向服务器端发出连接请求。

  (2)服务端监听到该请求,调用accept()函数接受请求,从而建立连接,并返回一个新的socket文件描述符专门处理该连接。

然后通信双方发送/接收数据:

  (1)服务器端调用write()或send()函数发送数据,客户端调用read()或者recv()函数接收数据。反之客户端发送数据,服务器端接收数据。

  (2)通信完成后,通信双方都需要调用close()或者shutdown()函数关闭socket对象。

 

类比电话通信,面向连接的socket通信实现图

 

必发88手机版 1

 

展示一个代码示例:

服务端:

#include<stdio.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<string.h>
#include<unistd.h>
#include <arpa/inet.h>
#include<pthread.h>

static void usage(const char *proc)
{
    printf("Please use :%s [IP] [port]n",proc);
}

void thread_run(void *arg)
{
    printf("creat a new threadn");
    int fd = (int)arg;
    char buf[1024];

    while(1){
        memset(buf,'\0',sizeof(buf));
        ssize_t _s = read(fd,buf,sizeof(buf) - 1);
        if(_s > 0){
            buf[_s] = '\0';
            printf("client say : %sn",buf);
        }    
        memset(buf,'\0',sizeof(buf));
        printf("please Enter: ");
        fflush(stdout);
        ssize_t _s2 = read(0,buf,sizeof(buf) - 1);
        if(_s2 > 0){
            write(fd,buf,strlen(buf));
        }
    }
}

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

    //1.creat socket

    int sock = socket(AF_INET,SOCK_STREAM,0);
    if(sock < 0){
        perror("creat socket errorn");
        return 1;
    }

    struct sockaddr_in local;
    local.sin_family = AF_INET;
    local.sin_port = htons(atoi(argv[2]));
    local.sin_addr.s_addr = inet_addr(argv[1]);

    //2.bind

    if(bind(sock,(struct sockaddr*)&local,sizeof(local)) < 0){
        perror("bind errorn");
        close(sock);
        return 2;
    }

    //3.listen

    if(listen(sock,10) < 0){
        perror("listen errorn");
        close(sock);
        return 3;
    }

    printf("bind and listen success!wait accept...n");

    //4.accept

    struct sockaddr_in peer;
    socklen_t len = sizeof(peer);
    while(1){

        int fd = accept(sock,(struct sockaddr*)&peer ,&len);

        if(fd < 0){
            perror("accept errorn");
            close(sock);
            return 4;
        }

        printf("get connect,ip is : %s port is : %dn",inet_ntoa(peer.sin_addr),ntohs(peer.sin_port));

        pthread_t id;
        pthread_create(&id,NULL,thread_run,(void*)fd);

        pthread_detach(id);

    }
    close(sock);
    return 0;
}

客户端:

#include<stdio.h>
#include<unistd.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<string.h>
#include<errno.h>
#include<netinet/in.h>
#include<arpa/inet.h>

static void usage(const char *proc)
{
    printf("please use : %s [ip] [port]n",proc);
}
int main(int argc,char *argv[])
{
    if( argc != 3 ){
        usage(argv[0]);
        exit(1);
    }

    int sock = socket(AF_INET,SOCK_STREAM,0);
    if(sock < 0){
        perror("socket error");
        return 1;
    }

    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]);


    int ret = connect(sock,(struct sockaddr*)&remote,sizeof(remote));
    if(ret < 0){
        printf("connect failed:%sn",strerror(errno));
        return 2;
    }

    printf("connect success!n");

    char buf[1024];
    while(1){
        memset(buf,'\0',sizeof(buf));
        printf("please enter:");
        fflush(stdout);
        ssize_t _s = read(0,buf,sizeof(buf)-1);
        if(_s > 0){
            buf[_s - 1] = '\0';
            write(sock,buf,strlen(buf));
            _s = read(sock,buf,sizeof(buf)-1);
            if(_s > 0){
                if(strncasecmp(buf,"quit",4) == 0){
                     printf("qiutn");
                     break;
                 }
                buf[_s -1] = '\0';
                printf("%sn",buf);
            }
        }
    }
    close(sock);
    return 0;
}

 

UDP网络通信编程

 客户不与服务器建立链接,而是管使用sendto函数给服务器发送数据报,其中必须指定目的地址(即服务器地址)作为参数。类似的,服务器不接受来自客户的连接,而只管调用

revcfrom函数等待来自某个客户数据的到达。revcfrom将与所接受到的数据报一道返回客户的协议地址,因此服务器可以把响应发送给正确的客户。

 

必发88手机版 2

 int sendto (int s, const void *buf, int len, unsigned int flags, const struct sockaddr *to, int tolen);

int recvfrom(int s, void *buf, int len, unsigned int flags, struct sockaddr *from, int *fromlen);

第一个参数为发送的目标socket对象。

第二个参数为欲发送的数据信息。

第三个参数为发送数据的大小。

第四个参数为flags,如send函数所示。

第五个参数欲发送数据的目标地址,其结构体前面已经介绍。

第六个参数为此结构体的大小。

必发88手机版 3服务端代码示例: 必发88手机版 4

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

int main(int argc,char *argv[])
{
    if(argc != 3){
        printf("Please Enter: %s [ip] [port]",argv[0]);
        return 1;
    }

    int sock = socket(AF_INET,SOCK_DGRAM,0);
    if(sock < 0){
        perror("socket error");
        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(bind(sock,(struct sockaddr*)&remote,sizeof(remote)) < 0){
        perror("bind error");
        return 3;
    }

    int done = 0;
    struct sockaddr_in peer;
    socklen_t len = sizeof(peer);

    char buf[1024];
    while(!done){
        memset(buf,'\0',sizeof(buf));
        printf("Please Enter:");
        fflush(stdout);
        ssize_t _s = read(0,buf,sizeof(buf)-1 );
        if(_s > 0){
            buf[_s -1] = '\0';
            sendto(sock,buf,sizeof(buf),0,(struct sockaddr*)&remote,sizeof(remote));

            memset(buf,'\0',sizeof(buf));
            recvfrom(sock,buf,sizeof(buf),0,(struct sockaddr*)&peer,&len);
            printf("server echo %s,socket :&s:&dn",buf,inet_ntoa(peer.sin_addr),ntohs(peer.sin_port));
        }
    }
    return 0;
}

客户端代码示例:

socket网络编程基础 tcp协议和udp协议,socketudp Socket TCP网络通信编程 首先,服务器端需要做以下准备工作: (1)调用socket()函数。建立...

socket():建立Socket对象。bind():绑定。在参数中需要传入绑定的IP地址和端口。listen():监听。只在服务器端有用,告诉操作系统开始监听之前绑定的IP地址和端口,可以在参数中指定允许排队的最大连接数量。connect(): 在客户端连接服务器。参数中需要指定服务器的地址和端口。accept():接受连接。只在服务器端有用,从监听到的连接中取出一个,并将其包装成一个新的Socket对象。send():发送数据。服务器和客户端均可以调用send()向对方发送数据,在send()的参数中传入要发送的数据,通过send()的返回值判断数据是否发送成功。recv():接收数据。服务器和客户端均可调用recv()从对方接收数据。close():关闭连接。通信中的任何一方可以调用close()发起关闭连接请求,另一方收到后也调用close()关闭连接。

首先,服务器端需要做以下准备工作:

 

  (1)调用socket()函数。建立socket对象,指定通信协议。

下面通过Python代码演示

  (2)调用bind()函数。将创建的socket对象与当前主机的某一个IP地和端口绑定。

服务端代码如下:

  (3)调用listen()函数。使socket对象处于监听状态,并设置监听队列大小。

import  socket


HOST='0.0.0.0'
PORT = 3434
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.bind((HOST,PORT))#绑定IP与端口
s.listen(1)

while True:
    conn,addr = s.accept()
    print('Client %s connected!'%str(addr) )#输出客户端的IP地址
    dt = '我来自服务端'
    message = 'Current time is '   str(dt)
    conn.send(message.encode())#向客户端发送时间
    print("Sent:",message)
    conn.close()#关闭链接

客户端需要做以下准备工作:

 

  (1)调用socket()函数。建立socket()对象,指定相同通信协议。

与服务器端对应的客户端代码如下:

  (2)应用程序可以显式的调用bind()函数为其绑定IP地址和端口,当然,也可以将这工作交给TCP/IP协议栈。

import socket #socket模块


HOST = '127.0.0.1'
PORT = 3434

s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect((HOST,PORT))
print('Connect %s:%d OK'%(HOST,PORT))
data = s.recv(1024)#接受数据,本次接收数据的最大长度为1024
print("Received:",data.decode())
s.close()#关闭链接

接着建立通信连接:

自行调试,查看执行结果!

  (1)客户端调用connect()函数。向服务器端发出连接请求。

注:客户端的Socket端口号由系统自动分配。

  (2)服务端监听到该请求,调用accept()函数接受请求,从而建立连接,并返回一个新的socket文件描述符专门处理该连接。

 

然后通信双方发送/接收数据:

  (1)服务器端调用write()或send()函数发送数据,客户端调用read()或者recv()函数接收数据。反之客户端发送数据,服务器端接收数据。

  (2)通信完成后,通信双方都需要调用close()或者shutdown()函数关闭socket对象。

 

类比电话通信,面向连接的socket通信实现图

 

必发88手机版 5

 

展示一个代码示例:

服务端:

#include<stdio.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<string.h>
#include<unistd.h>
#include <arpa/inet.h>
#include<pthread.h>

static void usage(const char *proc)
{
    printf("Please use :%s [IP] [port]n",proc);
}

void thread_run(void *arg)
{
    printf("creat a new threadn");
    int fd = (int)arg;
    char buf[1024];

    while(1){
        memset(buf,'\0',sizeof(buf));
        ssize_t _s = read(fd,buf,sizeof(buf) - 1);
        if(_s > 0){
            buf[_s] = '\0';
            printf("client say : %sn",buf);
        }    
        memset(buf,'\0',sizeof(buf));
        printf("please Enter: ");
        fflush(stdout);
        ssize_t _s2 = read(0,buf,sizeof(buf) - 1);
        if(_s2 > 0){
            write(fd,buf,strlen(buf));
        }
    }
}

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

    //1.creat socket

    int sock = socket(AF_INET,SOCK_STREAM,0);
    if(sock < 0){
        perror("creat socket errorn");
        return 1;
    }

    struct sockaddr_in local;
    local.sin_family = AF_INET;
    local.sin_port = htons(atoi(argv[2]));
    local.sin_addr.s_addr = inet_addr(argv[1]);

    //2.bind

    if(bind(sock,(struct sockaddr*)&local,sizeof(local)) < 0){
        perror("bind errorn");
        close(sock);
        return 2;
    }

    //3.listen

    if(listen(sock,10) < 0){
        perror("listen errorn");
        close(sock);
        return 3;
    }

    printf("bind and listen success!wait accept...n");

    //4.accept

    struct sockaddr_in peer;
    socklen_t len = sizeof(peer);
    while(1){

        int fd = accept(sock,(struct sockaddr*)&peer ,&len);

        if(fd < 0){
            perror("accept errorn");
            close(sock);
            return 4;
        }

        printf("get connect,ip is : %s port is : %dn",inet_ntoa(peer.sin_addr),ntohs(peer.sin_port));

        pthread_t id;
        pthread_create(&id,NULL,thread_run,(void*)fd);

        pthread_detach(id);

    }
    close(sock);
    return 0;
}

客户端:

#include<stdio.h>
#include<unistd.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<string.h>
#include<errno.h>
#include<netinet/in.h>
#include<arpa/inet.h>

static void usage(const char *proc)
{
    printf("please use : %s [ip] [port]n",proc);
}
int main(int argc,char *argv[])
{
    if( argc != 3 ){
        usage(argv[0]);
        exit(1);
    }

    int sock = socket(AF_INET,SOCK_STREAM,0);
    if(sock < 0){
        perror("socket error");
        return 1;
    }

    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]);


    int ret = connect(sock,(struct sockaddr*)&remote,sizeof(remote));
    if(ret < 0){
        printf("connect failed:%sn",strerror(errno));
        return 2;
    }

    printf("connect success!n");

    char buf[1024];
    while(1){
        memset(buf,'\0',sizeof(buf));
        printf("please enter:");
        fflush(stdout);
        ssize_t _s = read(0,buf,sizeof(buf)-1);
        if(_s > 0){
            buf[_s - 1] = '\0';
            write(sock,buf,strlen(buf));
            _s = read(sock,buf,sizeof(buf)-1);
            if(_s > 0){
                if(strncasecmp(buf,"quit",4) == 0){
                     printf("qiutn");
                     break;
                 }
                buf[_s -1] = '\0';
                printf("%sn",buf);
            }
        }
    }
    close(sock);
    return 0;
}

 

UDP网络通信编程

 客户不与服务器建立链接,而是管使用sendto函数给服务器发送数据报,其中必须指定目的地址(即服务器地址)作为参数。类似的,服务器不接受来自客户的连接,而只管调用

revcfrom函数等待来自某个客户数据的到达。revcfrom将与所接受到的数据报一道返回客户的协议地址,因此服务器可以把响应发送给正确的客户。

 

必发88手机版 6

 int sendto (int s, const void *buf, int len, unsigned int flags, const struct sockaddr *to, int tolen);

int recvfrom(int s, void *buf, int len, unsigned int flags, struct sockaddr *from, int *fromlen);

第一个参数为发送的目标socket对象。

第二个参数为欲发送的数据信息。

第三个参数为发送数据的大小。

第四个参数为flags,如send函数所示。

第五个参数欲发送数据的目标地址,其结构体前面已经介绍。

第六个参数为此结构体的大小。

必发88手机版 7服务端代码示例:

必发88手机版 8必发88手机版 9

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

int main(int argc,char *argv[])
{
    if(argc != 3){
        printf("Please Enter: %s [ip] [port]",argv[0]);
        return 1;
    }

    int sock = socket(AF_INET,SOCK_DGRAM,0);
    if(sock < 0){
        perror("socket error");
        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(bind(sock,(struct sockaddr*)&remote,sizeof(remote)) < 0){
        perror("bind error");
        return 3;
    }

    int done = 0;
    struct sockaddr_in peer;
    socklen_t len = sizeof(peer);

    char buf[1024];
    while(!done){
        memset(buf,'\0',sizeof(buf));
        printf("Please Enter:");
        fflush(stdout);
        ssize_t _s = read(0,buf,sizeof(buf)-1 );
        if(_s > 0){
            buf[_s -1] = '\0';
            sendto(sock,buf,sizeof(buf),0,(struct sockaddr*)&remote,sizeof(remote));

            memset(buf,'\0',sizeof(buf));
            recvfrom(sock,buf,sizeof(buf),0,(struct sockaddr*)&peer,&len);
            printf("server echo %s,socket :&s:&dn",buf,inet_ntoa(peer.sin_addr),ntohs(peer.sin_port));
        }
    }
    return 0;
}

客户端代码示例:

本文由必发88手机版发布,转载请注明来源:TCP实战练习,socket互连网编制程序基础