您的位置:首页 > 编程语言

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

2005-10-06 13:33 274 查看
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()函数。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: