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

UNIX上的socket编程(在solaris9/RethatEnterprise3上调试通过)

2013年03月18日 ⁄ 综合 ⁄ 共 4850字 ⁄ 字号 评论关闭

UNIX上的socket编程(在solaris9/RethatEnterprise3上调试通过)

Tcpserver.c //服务器端

#include <stdio.h>
#include <stdlib.h>
#include <strings.h>  /* for bzero */
#include <unistd.h>   /* for close */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define PORT 1234  /* Port that will be opened */
#define BACKLOG 1  /* Number of allowed connections */

int main(int argc, char *argv[])
{
  int listenfd, connectfd;   /* socket descriptors           */
  struct sockaddr_in server; /* server's address information */
  struct sockaddr_in client; /* client's address information */
  int sin_size;

  /* Create TCP socket */
  if((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1){
    /* handle exception */
    perror("Creating socket failed.");
    exit(0);
  } 

  /* set socket can be reused */
  int opt = SO_REUSEADDR;
  setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

  bzero(&server, sizeof(server)); /* fill server with 0s */
  server.sin_family = AF_INET;
  server.sin_port = htons(PORT);
  server.sin_addr.s_addr = htonl(INADDR_ANY);

  if (bind(listenfd, (struct sockaddr *)&server,
      sizeof(struct sockaddr)) == -1){
    /* handle exception */
    perror("Bind error!");
    exit(0);
  }

  if (listen(listenfd,BACKLOG) == -1){  /* calls listen() */
    perror("listen() error/n");
    exit(0);
  }

  while(1){
    sin_size = sizeof(struct sockaddr_in);

    if((connectfd = accept(listenfd,
        (struct sockaddr *)&client, &sin_size)) == -1){
      /* calls accept */
      perror("accept() error!/n");
      //return -1;
      break;
    }

    /* prints client's IP*/
    printf("You got a connection from %s/n",inet_ntoa(client.sin_addr));

    /* send to the client welcome message */
    send(connectfd, "Welcome to my server./n",22,0);

    close(connectfd); /*close connectfd */
  }

  close(listenfd);  /*close listenfd */
  exit(0);
}

//tcpclient 客户端

#include <stdio.h>
#include <unistd.h>
#include <strings.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define PORT 1234 /* open port on remote host */
#define MAXDATASIZE 100 /* Max number of bytes of data */

int main(int argc, char *argv[])
{
  int fd, numbytes; /* files descriptiors */
  char buf[MAXDATASIZE]; /* buf will stroe received text */
  struct hostent *he;    //structure that will get information about remote host
  struct sockaddr_in server; /* server's address information */

  if (argc != 2) {//this is used because our program will need one argument (IP)
    printf("Usage: %s <IP Address>/n",argv[0]);
    exit(0);
  } 

  if((he = gethostbyname(argv[1])) == NULL) { /* calls gethostbyname()*/
    printf("gethostbyname() error/n");
    exit(0);
  } 

  if((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {  /* calls socket() */
    printf("socket() error/n");
    exit(0);
  } 

  bzero(&server, sizeof(server));
  server.sin_family = AF_INET;
  server.sin_port = htons(PORT); /* htons() is needed again */
  //he->h_addr passes "*he"'s info to "h_addr"
  server.sin_addr = *((struct in_addr *)he->h_addr);
  //server.sin_addr.s_addr = htonl(INADDR_ANY);

  //calls connect()
  if(connect(fd, (struct sockaddr *)&server, sizeof(struct sockaddr)) == -1) {
    close(fd);
    printf("connect() error/n");
    exit(0);
  }

  if((numbytes = recv(fd, buf, MAXDATASIZE, 0)) == -1) {  /* calls recv() */
    printf("recv() error/n");
    exit(0);
  }

  buf[numbytes] = '/0';
  printf("Server Message: %s /n", buf);  /*it prints server's welcome message */

  close(fd); /* close fd */
}

solaris编译
cc –o tcpserver tcpserver.c –lsocket –lnsl
cc –o tcpclient tcpclient.c –lsocket –lsnt

linux编译
cc –o tcpserver tcpserver.c

一.服务器端步骤

1.创建套接字 2.绑定套接字 3.设置套接字为监听模式,进入被动接受连接请求状态
4.接受请求,建立连接 5.读/写数据 6.终止连接.

二.客户端步骤

1.创建套接字 2.与远程服务程序连接 3.读/写数据 4.终止连接

#include <sys/types.h>  #include <sys/socket.h>
int socket(int domain, int type, int protocol);

domain: 一般用AF_INET
type:SOCK_STREAM:以字节流形式通信,面向连接的协议使用这种形式。
SOCK_DGRAM:数据以独立的数据包形式流动,无连接协议使用这种形式。
SOCK_RAW:是低于传输层的低级协议或物理网络提供的套接字类型。他可访问内部网络接口。
protocol:IPPROTO_TCP:表示tcp协议
IPPROTO_UDP:表示udp协议.
返回值:成功 返回socket描述符,否则返回-1

#include <sys/types.h>  #include <sys/socket.h>
int bind(int s, const struct sockaddr *name, int namelen);

s:套接字描述符
name:本地套接字地址
namelen:本地套接字地址长度.
返回值:成功返回0 ,不成功返回-1。

#include <sys/types.h>  #include <sys/socket.h>
int listen(int s, int backlog);
s:套接字描述符
backlog:指定在请求队列中允许的最大请求数.
返回值:成功返回0,不成功返回-1

#include <sys/types.h>  #include <sys/socket.h>
int accept(int s, struct sockaddr *addr, socklen_t *addrlen);

s:套接字描述符
addr:是一个指向sockaddr变量的指针,该变量用来存放提出连接请求服务的主机的信息(某台主机从某个端口发出该请求)。
addrlen 通常为一个指向值为sizeof(struct sockaddr_in)的整形指针变量。
返回值:调用成功返回非负整数代表新的套接字,不成功返回-1

#include <sys/types.h>  #include <sys/socket.h>
int connect(int s, const struct sockaddr *name, int namelen);

该函数用于启动和远程主机的直接连接.
s:套接字描述符
name:是包含远程主机IP地址和端口号的指针.
namelen:是远程地址结构的长度.
返回值:成功返回0,不成功-1

ssize_t send(int s, const void *msg, size_t len, int flags);

s:套接字描述符
msg 是指向一个包含传输信息的数据缓冲区。
len 指明传送数据缓冲区的大小。
flags 是传输控制标志;0 常规操作,MSG_OOB 发送带外数据
MSG_DONTROUTE 通过最直接的路径发送数据,而忽略底层协议的路由设置

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

recv函数用于tcp套接字的数据接收
s是套接字描述符
buf是指向一个包含接收信息的数据缓冲区
len指明接受数据缓冲区的大小
flags 是传输控制标志:0 常规操作。如同read()函数。
MSG_PEEK 只查看数据而不读出数据,此意味着后续读操作仍然读出所察看的数据 。
MSG_OOB 忽略常规数据,而只读带外数据
MSG_WAITALL:recv()函数只有在将接收缓冲区填满后才返回。

返回值 调用成功返回接收数据的长度(以字节为单位),否自返回-1,当对方关闭连接时,返回的接收数据长度为0 。 通常以此来判断对方是否关闭.

int shutdown(int s, int how)

s是套接字描述符
how :0 不允许继续接受数据  1 不允许继续发送数据 2 不允许继续发送和接收数据。 全部为允许则用close()函数。

抱歉!评论已关闭.