TCP之socket编程

socket(套接字):IP地址+端口号,唯一标识网络中的一个进程

socket编程中建立连接的两个进程都有一个socket来标识唯一一个连接。

网络字节序:网络数据流有大小端之分,发送主机通常将发送缓冲区中的数据按内存地址从低到高的顺序发出,接收主机把从网络上接到的字节依次保存在接收缓冲区中,也是按内存地址从低到高的顺序保存,网络数据流的地址规定:先发出的数据是低地址,后发出的数据是

地址。

TCP/IP协议规定,网络数据流应采用大端字节序,即低地址高字节。

例:如果端口号是1000(0x3e8),则地址0是0x03,地址1是0xe8, 也就是先发0x03,再发0xe8,这16位在发送主机的缓冲区中也应该是低地址存0x03,高地址存0xe8。但是,如果发送主机是小端字节序的,这16位端口号被解释成0xe803,不是1000。因此,发送主机把1000填到发送缓冲区之前需要做字节序的转换。同样地,接收主机如果是小端字节序的, 接到16位的源端口号也要做字节序的转换。如果主机是大端字节序的,发送和接收都不需要做转换。同理,32位的IP地址也要考虑网络字节序和主机字节序的问题。

服务器端socket:

1.创建套接字:int socket(int domain,int type,int protocol) //domain底层采用何种协议,传输类型,TCP面向字节流式

2.使用struct socketaddr_in 结构体填充网络方面信息

3.绑定:将套接字信息填充到内核中

4.设置套接字状态为监听状态,接收客户端发来的连接请求

5.等待客户请求,当请求连接来后,接受连接请求,返回一个新的对应于此次连接的套接字(accept)

6.新的套接字和客户端进行通信

accept函数:在一个套接口接受一个连接。

int accept(int sockfd,struct sockaddr*addr,socklen_t* addrlen)

sockfd和 listen() 中套接字描述符相同。addr要求接入的信息所要去的地方。返回值:如果执行成功,返回值为0,否则设置错误码,返回-1。

bind函数:将一本地地址与一套接口捆绑。

int bind(int sockfd, const struct sockaddr* addr, socklen_t len);

适用于未连接的数据报或流类套接口,在connect()listen()调用前使用。当用socket()创建套接口后,它便存在于一个名字空间(地址族)中,但并未赋名。bind()函数通过给一个未命名套接口分配一个本地名字来为套接口建立本地捆绑(主机地址/端口号)。

服务器端代码:

 1 #include<stdio.h>
  2 #include<string.h>
  3 #include<stdlib.h>
  4 #include<sys/types.h>
  5 #include<sys/socket.h>
  6 #include<netinet/in.h>
  7 #include<arpa/inet.h>
  8 #include<pthread.h>
  9 int start(int _port,char* ip)
 10 {   
 11     //1.create sock
 12     int listen_sock=socket(AF_INET,SOCK_STREAM,0);
 13     if(listen_sock < 0){
 14         perror("sock");
 15         exit(1);
 16     }
 17     //2.fill information 
 18     struct sockaddr_in local;
 19     local.sin_family=AF_INET;
 20     local.sin_port=htons(_port);
 21     local.sin_addr.s_addr=inet_addr(ip);
 22     //3.bind
 23     if(bind(listen_sock,(struct sockaddr*)&local,sizeof(local))<0)
 24     {
 25         perror("bind");
 26         exit(2);
 27     }
 28     //4.set listen 
 29     if(listen(listen_sock,5)<0)
 30     {
 31         perror("listen");
 32         exit(3);
 33     }
 34     return listen_sock;
 35 
 36    
 37 }
 38 void usage(const char *proc)
 39 {   
 40     printf("usage:%s [ip] [port]\n",proc);
 41 }
 42 
 43 void* thread_run(void* arg)
 44 {
 45     int sock =(int)arg;
 46     char buf[1024];
 47     while(1)
 48     {
 49         memset(buf,‘\0‘,sizeof(buf));
 50         ssize_t _size=read(sock,buf,sizeof(buf)-1);
 51         if(_size<0)
 52         {
 53             printf("read fail...\n");
 54             exit(1);
 55         }else if(_size==0)
 56         {
 57             printf("closed connect...\n");
 58             exit(2);
 59         }else
 60         {
 61             printf("client# %s\n",buf);
 62         }
 63     }
 64 }
 65 
 66 int main(int argc,char* argv[])
 67 {
 68     if(argc!=3)
 69     {
 70         usage(argv[0]);
 71         exit(1);
 72     }
 73     int listen_sock=start(atoi(argv[2]),argv[1]);
 74     struct sockaddr_in client;
 75     socklen_t len=sizeof(client);
 76     int done=0;
 77     while(!done)
 78     {
 79         int new_sock=accept(listen_sock,(struct sockaddr*)&client,&len);
 80         if(new_sock<0)
 81         {
 82             perror("accept");
 83             continue;
 84         }
 85         printf("get a connect... [sock]:%d [ip]:%s [port]:%d\n",new_sock,inet_ntoa(cl ient.sin_addr),ntohs(client.sin_port));
 86    
 87 #ifdef _V1_
 88         while(1)
 89         {
  90             char buf[1024];
 91             memset(buf,‘\0‘,sizeof(buf));
 92             ssize_t _size=read(new_sock,buf,sizeof(buf)-1);
 93             if(_size<0)
 94             {
 95                 printf("read fail...\n");
 96                 exit(1);
 97             }else if(_size==0)
 98             {
 99                 printf("closed connect...\n");
100                 exit(2);
101             }else
102             {
103                 printf("client# %s",buf);
104             }
105         }
106     }
107 #elif _V2_
108         pid_t id=fork();
109         if(id<0)
110         {
111             printf("create fail...\n");
112             exit(3);
113         }else if(id==0)
114         {
115             close(listen_sock);//close listen_sock,only deal with I/Ostream
116             while(1)
117             {
118                 char buf[1024];
119                 memset(buf,‘\0‘,sizeof(buf));
120                 ssize_t _size=read(new_sock,buf,sizeof(buf)-1);
121                 if(_size<0)

121                 if(_size<0)

122                 {

123                     printf("read fail...\n");

124                     exit(1);

125                 }else if(_size==0)

126                 {

127                     printf("closed connect...\n");

128                     exit(2);

129                 }else

130                 {

131                     printf("client# %s\n",buf);

132                 }

133             }

134             close(new_sock);

135         }else

136         {

137             close(new_sock);

138         }

139     }

140

141 #elif _V3_

142         pthread_t tid;

143         if(tid=pthread_create(&tid,NULL,thread_run,(void*) new_sock)<0)

144         {

145             perror("pthread_create");

146             exit(2);

147         }

148         pthread_detach(tid);

149     }

150 #else

151     printf("default\n");

152     }

153 #endif

154    return 0;

155 }

connect函数:

int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);

向服务器端发送连接请求,只维护一个连接,连接成功后通过sock进行传输
客户端:

1.创建套接字(进行三次握手)

2.向服务器发连接请求

3.传输数据

4.关闭套接字(四次挥手,即释放链接)

客户端代码:

1 #include<stdio.h>

2 #include<string.h>

3 #include<stdlib.h>

4 #include<sys/types.h>

5 #include<sys/socket.h>

6 #include<netinet/in.h>

7 #include<arpa/inet.h>

8

9 void usage(char* proc)

10 {

11     printf("usage:%s [remoteip] [remoteport]\n",proc);

12 }

13 int main(int argc,char*argv[])

14 {

15     if(argc!=3)

16     {

17         usage(argv[0]);

18         exit(1);

19     }

20     char* remote_ip=argv[1];

21     int remote_port=atoi(argv[2]);

22     int sock=socket(AF_INET,SOCK_STREAM,0);

23     if(sock < 0)

24     {

25         perror("socket");

26         exit(2);

27     }

28     struct sockaddr_in remote;

29     remote.sin_family=AF_INET;

30     remote.sin_port=htons(remote_port);

31     remote.sin_addr.s_addr=inet_addr(remote_ip);

32     //send SYN head

33     if(connect(sock,(struct sockaddr*)&remote,sizeof(remote))<0)

34     {

35         perror("connect");

36         exit(3);

37     }

38     char msg[1024];

39     while(1)

40     {

41         memset(msg,‘\0‘,sizeof(msg));

42         printf("please input msg:");

43         fflush(stdout);

44         if(read(0,msg,sizeof(msg))>0){

45             write(sock,msg,strlen(msg));

46         }

47

48     }

49     return 0;

50 }

运行结果:

单用户:

利用线程模拟多用户:

时间: 2024-10-13 08:47:48

TCP之socket编程的相关文章

Java TCP/UDP socket 编程流程总结

最近正好学习了一点用java socket编程的东西.感觉整体的流程虽然不是很繁琐,但是也值得好好总结一下. Socket Socket可以说是一种针对网络的抽象,应用通过它可以来针对网络读写数据.就像通过一个文件的file handler就可以都写数据到存储设备上一样.根据TCP协议和UDP协议的不同,在网络编程方面就有面向两个协议的不同socket,一个是面向字节流的一个是面向报文的. 对socket的本身组成倒是比较好理解.既然是应用通过socket通信,肯定就有一个服务器端和一个客户端.

网络 基于TCP协议socket编程

一.socket编程         1.socket编程        socket这个词可以表示很多概念: 在TCP/IP协议中,"IP地址+TCP或UDP端号"唯一标识网络通讯中的一个进程,"IP地址+端口号"就称为socket.在TCP协议中,建立连接的两个进程各自有一个socket来标识,那么这两个socket组成 的socket pair就唯一标识一个连接. socket本义有"插座"的意思,因此用来描述网络连接的一对一关系.    

一个项目看java TCP/IP Socket编程

前一段时间刚做了个java程序和网络上多台机器的c程序通讯的项目,遵循的是TCP/IP协议,用到了java的Socket编程.网络通讯是java的强项,用TCP/IP协议可以方便的和网络上的其他程序互通消息. 先来介绍下网络协议:     TCP/IP         Transmission Control Protocol 传输控制协议         Internet Protocol 互联网协议     UDP         User Datagram Protocol 用户数据协议

【网络编程笔记】简单的TCP协议 socket编程(C语言版服务器和客户端)

下图是一般socket 编程图. 服务器的建立: 获取的本机名,用来解析得到本机的IP地址的:接着就绑定IP地址成功,然后服务器就处于监听状态,等待客户端的连接.也就是接下来就是TCP/IP的三次握手的操作,该操作成功了服务器和客户端就可以进行通信了.以下是注释代码: 1 void socketConnect() 2 { 3 char Server_name[128]; 4 WSADATA wsaData; 5 struct hostent *hp; 6 struct sockaddr_in a

基于TCP的socket 编程

一.对socket的理解 1.socket本身有"插座"的意思,因此用来描述网络连接的一对一关系. 2.在TCP/IP协议中,"IP地址+TCP/UDP端口号"唯一标识网络通信中的一个进程,"IP地址+端口号"就称为socket. 3.在TCP协议中,建立连接的两个进程各自有一个socket来标识,那么这两个socket组成的socketpair 就唯一标志一个连接. 二.网络数据流 网络数据流有大端和小端之分.发送主机通常将发送缓冲区中的数据按

Java Tcp协议socket编程学习

以下是一对一的通信编程实现,后续会继续学习一个服务器监听多个客户端的实现. 我学习到的主要步骤 第一步:以特定端口(如4800)新建socket对象第二步:以系统输入设备构造BufferedReader对象,该对象用于接收系统键盘输入的字符第三步:以socket对象 得到输出流来构造PrintWriter第四步:以socket对象得到输入流来构造相应的BufferedReader对象,该对象用于接收server端发送过来的信息 我理解到的关闭socket:先开的后关闭,socket最后关闭. 以

Go语言TCP/UDP Socket编程

1. TCP编程 TCPClient // TCPClient project main.go package main import ( "fmt" "net" "os" ) func main() { var buf [512]byte if len(os.Args) != 2 { fmt.Fprintf(os.Stderr, "Usage: %s host:port ", os.Args[0]) os.Exit(1) }

模拟客户端登陆(基于TCP的Socket编程)

1.客户端  package com.ljb.app.socket; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintWriter; import java.net.Socket; import java.n

基于TCP协议下的socket编程

socket: TCP/IP协议中一个端口号和一个IP地址绑定在一起就生成一个socket就表示了网络中唯一的一个进程,它是全双工的工作方式. 基于TCP的socket编程 函数的使用: 1.socket()         #include <sys/types.h>          /* See NOTES */        #include <sys/socket.h>        int socket(int domain, int type, int protoco