c socket编程

1、UDP

(1)client.c

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

#define REMOTEPORT 4567
#define REMOTEIP "127.0.0.1"//这是server端的IP,如在两台机器上测试,只需更改此IP为server端IP

/*
所在头文件:#include <strings.h>
函数原型:extern void bzero(void *s, int n);
函数功能:置字节字符串s的前n个字节为零且包括‘\0’。
入口参数:字符串,整型。
出口参数:无返回值。
*/

/*
所在头文件:#include <arpa/inet.h>
函数原型:in_addr_t inet_addr(const char *cp);
函数功能:将一个点间隔地址转换成一个in_addr。
入口参数:点间隔地址字符串。
出口参数:in_addr 型地址。
*/

/*
所在头文件:#include <unistd.h>
函数原型:ssize_t read(int fd, void *buf, size_t count);
函数功能:从文件流描述符fd中读数据到buf中,长度不超过count
入口参数:文件流描述符,缓存,长度
出口参数:读到的字符总长度。
*/

/*
所在头文件:#include < sys/types.h > #include < sys/socket.h >
函数原型:int sendto (int s,void * msg,int len, unsigned int flags,struct sockaddr *to,int tolen);
函数功能:将本机编号为s的套接字字符串msg发送给to套接字结构体所代表的地址及端口;
入口参数:s--socket编号,msg--需要发送的字符串,len--发送的字符串长度,flags--一般置0,to--套接子结构体类型,tolen--套接字结构体长度;
出口参数:传送成功,返回传送的字符个数;失败,返回-1。
*/

int main(int argc,char *argv[])
{
    int s,len;
    struct sockaddr_in addr;//套接字数据类型,用来存放一个套接字,这里是目的套接字
    int addr_len;
    char msg[256];   
    int i=0;
    /*if else创建本地即客户端套接字*/
    if(( s = socket(AF_INET,SOCK_DGRAM,0))<0) //创建套接字,返回套接字编号
    {
        perror("error");
        exit(1);
    }
    else
    {
        printf("socket created successfully!\n");
        printf("socket id:%d\n",s);
        printf("remote ip:%s\n",REMOTEIP);
        printf("remote port: %d\n\n",REMOTEPORT);
    }
    /*if else创建本地即客户端套接字*/

    addr_len=sizeof(struct sockaddr_in);
    bzero(&addr,sizeof(addr));
    /*外地即服务端套接字*/
    addr.sin_family=AF_INET;
    addr.sin_port=htons(REMOTEPORT);
    addr.sin_addr.s_addr=inet_addr(REMOTEIP);
    /*外地即服务端套接字*/

    while(1)
    {
        bzero(msg,sizeof(msg));

        printf("Please Input message\n");
        printf("The serial number of the message:%d\n",i);
        i++;
        len=read(STDIN_FILENO,msg,sizeof(msg));//从键盘(终端)键入msg

        sendto(s,msg,len,0,(struct sockaddr *)&addr,addr_len);//发送msg给目的套接字addr
        printf("Send message from client:%s",msg);

        len=recvfrom(s,msg,sizeof(msg),0,(struct sockaddr *)&addr,&addr_len);//接受目的套接字传来的msg

        printf("Received message from server:%s\n",msg);
    }

}

(2)server.c

#include &lt;stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>

#define LOCALPORT 4567

int main(int argc,char *argv[])
{
    int mysock,len;
    struct sockaddr_in addr;
    int i=0;
    char msg[256];
    int addr_len;
    /*创建本地即服务端套接字*/
    if((mysock=socket(AF_INET,SOCK_DGRAM,0))<0)
    {
        perror("error");
        exit(1);
    }
    else
    {
        printf("socket created successfully!\n");
        printf("socked id:%d\n",mysock);
    }
    /*创建本地即服务端套接字*/
    addr_len=sizeof(struct sockaddr_in);
    bzero(&addr,sizeof(addr));

    /*本地即server套接字属性*/
    addr.sin_family=AF_INET;
    addr.sin_port=htons(LOCALPORT);
    addr.sin_addr.s_addr=htonl(INADDR_ANY);//INADDR_ANY 0.0.0.0 即将地址清零,系统找到的是本机IP
    /*本地即server套接字属性*/
    /*绑定本地server套接字的端口和IP*/
    if(bind(mysock,(struct sockaddr *)&addr,sizeof(addr))&lt;0)
    {
        perror("error");
        exit(1);
    }
    else
    {
        printf("bind successfully!\n");       
        printf("local port:%d \n\n",LOCALPORT);
    }
    /*绑定本地server套接字的端口和IP*/

    while(1)
    {
        bzero(msg,sizeof(msg));
        len=recvfrom(mysock,msg,sizeof(msg),0,(struct sockaddr *)&addr,&addr_len);
        printf("The serial number of the message:%d\n",i);
        i++;

        printf("The message Received from client:%s",msg);
        printf("Received message length:%d\n",len);
        printf("Received message from:%s\n",inet_ntoa(addr.sin_addr));
        printf("Reply message from server:%s\n",msg);
        sendto(mysock,msg,len,0,(struct sockaddr *)&addr,addr_len);
    }
}

2.TCP

(1)client.c

#include &lt;stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>

#define PORT 5678
#define REMOTE_IP "127.0.0.1"

int main()
{
    int s;
    struct sockaddr_in addr;
    char mybuffer[256];

    if((s=socket(AF_INET,SOCK_STREAM,0))<0)
    {
        perror("socket");
        exit(1);
    }
    else
    {
        printf("socket created successfully!.\n");
        printf("socked id:%d\n",s);
    }

    bzero(&addr,sizeof(addr));
    addr.sin_family=AF_INET;
    addr.sin_port=htons(PORT);
    addr.sin_addr.s_addr=inet_addr(REMOTE_IP);

    if(connect(s,(struct sockaddr *)&addr,sizeof(addr))&lt;0)
    {
        perror("connect");
        exit(1);
    }
    else
    {
        printf("connected ok!\n");
        printf("remote ip:%s\n",REMOTE_IP);
        printf("remote port:%d\n",PORT);
    }

    recv(s,mybuffer,sizeof(mybuffer),0);
    printf("%s\n",mybuffer);
    while(1)
    {
        bzero(mybuffer,sizeof(mybuffer));
        read(STDIN_FILENO,mybuffer,sizeof(mybuffer));//从键盘读信息
        /*发送并接收数据(if else意思是发送成功则执行接收,发送失败则退出)*/
        if(send(s,mybuffer,sizeof(mybuffer),0)&lt;0)//发送从键盘读到的信息
        {
            perror("send");
            exit(1);
        }
        else
        {
            bzero(mybuffer,sizeof(mybuffer));
            recv(s,mybuffer,sizeof(mybuffer),0);//接收server端的信息
            printf("received from server:%s\n",mybuffer);
        }
        /*发送并接收数据(if else意思是发送成功则执行接收,发送失败则退出)*/
    }
}

(2)

server.c

#include &lt;stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>

#define PORT 5678
#define MAX 10

/*面向连接套接字server端*/

/*
所在头文件:#include <sys/select.h>
函数原型:int select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *timeout);
函数功能:一个进程同时处理多个文件描述符是很常见的情况。
入口参数:
出口参数:1、正常情况返回就绪的文件描述符个数;2、timeout时长无设备准备好,返回0;3、若select被某个信号中断,返回-1,并设置errno为EINTR;4、若出错,则返回-1,并设置相应的errno。
*/
int main()
{
    int sockfd,newsockfd,is_connected[MAX],fd;
    struct sockaddr_in addr;
    int addr_len = sizeof(struct sockaddr_in);
    fd_set myreadfds;//定义文件描述符集合
    char msgbuffer[256];
    char msg[]="The message is from server:connected successfully.\n";
    /*创建本地套接字*/
    if((sockfd=socket(AF_INET,SOCK_STREAM,0))<0)
    {
        perror("socket");
        exit(1);
    }
    else
    {   
        printf("socket created successfully!\n");
        printf("socket id:%d\n",sockfd);
    }
    /*创建本地套接字*/
    /*允许地址重用*/
    int ret,on;
    on=1;
    ret=setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));
    /*允许地址重用*/

    /*本地套接子属性*/
    bzero(&addr,sizeof(addr));
    addr.sin_family=AF_INET;
    addr.sin_port=htons(PORT);
    addr.sin_addr.s_addr=htonl(INADDR_ANY);
    /*本地套接子属性*/

    /*绑定本地套接子端口和IP等属性*/
    if(bind(sockfd,(struct sockaddr *)&addr,sizeof(addr))&lt;0)
    {
        perror("connect");
    }
    else
    {
        printf("connected successfully!\n");
        printf("local port:%d\n",PORT);
    }
    /*绑定本地套接子端口和IP等属性*/

    /*server监听,等待client连接,最大连接数为3*/
    if(listen(sockfd,3)&lt;0)
    {
        perror("listen");
        exit(1);
    }
    else
    {
        printf("listening......\n");
    }
    /*server监听,等待client连接,最大连接数为3*/
    for(fd=0;fd&lt;MAX;fd++)
    {
        is_connected[fd]=0;
    }

    while(1)
    {
        FD_ZERO(&myreadfds);//文件描述符集合中所有位置0
        FD_SET(sockfd,&myreadfds);//将文件描述符的sockfd位置1(本地套接字位置1)
        for(fd=0;fd&lt;MAX;fd++)
        {
            if(is_connected[fd])
            {
                FD_SET(fd,&myreadfds);
            }
        }
        if(!select(MAX,&myreadfds,NULL,NULL,NULL))
        {
            continue;
        }
        for(fd=0;fd&lt;MAX;fd++)   
        {
            if(FD_ISSET(fd,&myreadfds))           
            {   
                if(sockfd==fd)
                {
                    if((newsockfd=accept(sockfd,(struct sockaddr *)&addr,&addr_len))&lt;0)
                    {
                        perror("accept");
                    }
                    write(newsockfd,msg,sizeof(msg));//给客户端发送信息
                    is_connected[newsockfd]=1;
                    printf("connect from%s\n",inet_ntoa(addr.sin_addr));
                }
                else
                {   
                    bzero(msgbuffer,sizeof(msgbuffer));
                    if(read(fd,msgbuffer,sizeof(msgbuffer))&lt;=0)
                    {
                        printf("connect closed.\n");
                        is_connected[fd]=0;
                        close(fd);
                    }
                    else
                    {
                        write(fd,msgbuffer,sizeof(msgbuffer));
                        printf("message:%s\n",msgbuffer);
                    }
                }
            }
        }
    }
}

(3)运行

gcc –o client.exe client.c

gcc –o server.exe server.c

在两个终端分别运行./client.c    ./server.c

client.c终端输入字符串

且先运行server

 

套接字函数介绍

1、socket函数

#include &lt;sys/socket.h>

int socket(int family,int type,int protocol);

功能:

创建一个套接口

入口:

family——指明协议族,一般是AF_INET(IPv4协议);

type——有SOCK_STREAM、SOCK_DGRAM、SOCK_SEQPACKET、SOCK_RAW;

protocol——IPPROTO_TCP  IPPROTO_UDP  IPPROTO_SCTP

出口:

正确,套接字字符描述符,非负整数;出错,-1

posted @ 2012-09-23 20:07  helloweworld  阅读(419)  评论(0编辑  收藏  举报