精通
英语
和
开源
,
擅长
开发
与
培训
,
胸怀四海
第一信赖
要点:
sd=socket(domain,type,protocol);
指定通信域,类型和协议
bind(sd,&serv_addr,addrlen);
listen(sd,backlog)
confd=accept(sd,&serv_addr,addrlen);
read(confd,buf,nbytes);
write(cnofd,buf,nbytes);
上面是使用UNIX的I/O读写方式,使用发送和接收函数在随后讨论
close(confd);
close(sd);//注意,这里是服务器的socket,bind用的socket
shutdown(sd,how);
#include <sys/types.h>
#include <sys/socket.h>
int bind(int sd,struct sockaddr*my_addr,socklen_t addrlen);
参数和connect()函数类似,除了const修饰符从地址结构上被删除了,这意味着这个参数能修改。然而,在些情况下,Linux好象不遵守通常的函数原型,虽然这些原型在其它系统上使用,实际上你能检查到这个地址并没有实际上修改过。
int sd; short int port=50000; struct sockaddr_in addr; struct in_addr inaddr; … sd=socket(PF_INET,SOCK_STREAM,0); memset(addr,0,sizeof(addr)); addr.sin_family=AF_INET; addr.sin_port=htons(port); addr.sin_addr.s.addr=inet_addr(“192.168.1.1”); bind(sd,(struct sockaddr*)&addr,sizeof(struct sockaddr));出于简洁的目的,我们使用了旧风格的inet_addr()函数,而不是inet_aton()。同样注意到我们谨慎地把地址结构体内存清0,确保服务端口以合适的网络顺序保存。
struct sockaddr_in check; int check_len; … bind(…); getsockname(sd,(struct sockaddr*)&check,&check_len);
printf(“selected port %d\n”,ntohs(check.sin_port);
my_addr.sin_addr.s_addr=htonl(INADDR_ANY);
内核会用服务运行的机器上的IP来填充。
struct sockaddr_un addr; … sd=socket(PF_UNIX,SOCK_STREAM,0); addr.sun_family=AF_UNIX; strcpy(addr.sun_path,”/tmp/mysock”); bind(sd,(struct sockaddr*)&addr,sizeof(addr));
EBADF:无效的描述符。
int yes=1; setsockopt(sd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(yes));在socket创建后,bind前,调用上面代码,就可以解决问题。后面讲修改socket选项。
#include <sys/socket.h>
int listen(int sd,int backlog);
#include <sys/types.h>
#include <sys/socket.h>
int accept(int sd,struct sockaddr*addr,socklen_t *addrlen);
int getpeername(int sd,const struct sockaddr *rem_addr,socklen_t addrlen);
会获取对端socket的地址和端口数字。
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>
#define MSG_LEN 1024
int main (void) { struct sockaddr_un uaddr; int rc, sd, cd; socklen_t alen; char message[MSG_LEN]; uaddr.sun_family = AF_UNIX; strcpy (uaddr.sun_path, "/tmp/mysock"); sd = socket (PF_UNIX, SOCK_STREAM, 0); unlink ("/tmp/mysock");//保证这个文件入口是空闲的 bind (sd, (struct sockaddr *)&uaddr, sizeof (uaddr)); listen (sd, 5); for (;;) { cd = accept (sd, NULL, &alen); rc = read (cd, message, sizeof (message)); write (STDOUT_FILENO, message, rc); close (cd); } close (sd); exit (EXIT_SUCCESS); }
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#define MSG_LEN 1024
#define PORT_NUMBER 7177
int main (void) { struct sockaddr_in addr, con_addr; int rc, sd, cd, yes = 1; socklen_t alen; char message[MSG_LEN]; //构造地址 addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl (INADDR_ANY);//注意网络字节顺序处理 addr.sin_port = htons (PORT_NUMBER); sd = socket (PF_INET, SOCK_STREAM, 0); //设置端口使用可以重用 setsockopt (sd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof (yes)); bind (sd, (struct sockaddr *)&addr, sizeof (addr)); listen (sd, 5);//listen的第二个参数一般设置为5 for (;;) { printf ("\nAccepting input on port %d\n", PORT_NUMBER); cd = accept (sd, (struct sockaddr *)&con_addr, &alen); rc = read (cd, message, sizeof (message)); write (STDOUT_FILENO, message, rc); write (cd, message, rc); printf ("Received the end of input\n\n"); close (cd); } close (sd); exit (EXIT_SUCCESS); }